Completed
Branch dev (64e3a7)
by
unknown
13:10 queued 05:44
created
core/EE_Dependency_Map.core.php 1 patch
Indentation   +1125 added lines, -1125 removed lines patch added patch discarded remove patch
@@ -20,1129 +20,1129 @@
 block discarded – undo
20 20
  */
21 21
 class EE_Dependency_Map
22 22
 {
23
-    /**
24
-     * This means that the requested class dependency is not present in the dependency map
25
-     */
26
-    const not_registered = 0;
27
-
28
-    /**
29
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
-     */
31
-    const load_new_object = 1;
32
-
33
-    /**
34
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
-     */
37
-    const load_from_cache = 2;
38
-
39
-    /**
40
-     * When registering a dependency,
41
-     * this indicates to keep any existing dependencies that already exist,
42
-     * and simply discard any new dependencies declared in the incoming data
43
-     */
44
-    const KEEP_EXISTING_DEPENDENCIES = 0;
45
-
46
-    /**
47
-     * When registering a dependency,
48
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
-     */
50
-    const OVERWRITE_DEPENDENCIES = 1;
51
-
52
-    /**
53
-     * @type EE_Dependency_Map $_instance
54
-     */
55
-    protected static $_instance;
56
-
57
-    /**
58
-     * @var ClassInterfaceCache $class_cache
59
-     */
60
-    private $class_cache;
61
-
62
-    /**
63
-     * @type RequestInterface $request
64
-     */
65
-    protected $request;
66
-
67
-    /**
68
-     * @type LegacyRequestInterface $legacy_request
69
-     */
70
-    protected $legacy_request;
71
-
72
-    /**
73
-     * @type ResponseInterface $response
74
-     */
75
-    protected $response;
76
-
77
-    /**
78
-     * @type LoaderInterface $loader
79
-     */
80
-    protected $loader;
81
-
82
-    /**
83
-     * @type array $_dependency_map
84
-     */
85
-    protected $_dependency_map = [];
86
-
87
-    /**
88
-     * @type array $_class_loaders
89
-     */
90
-    protected $_class_loaders = [];
91
-
92
-
93
-    /**
94
-     * EE_Dependency_Map constructor.
95
-     *
96
-     * @param ClassInterfaceCache $class_cache
97
-     */
98
-    protected function __construct(ClassInterfaceCache $class_cache)
99
-    {
100
-        $this->class_cache = $class_cache;
101
-        do_action('EE_Dependency_Map____construct', $this);
102
-    }
103
-
104
-
105
-    /**
106
-     * @return void
107
-     * @throws InvalidAliasException
108
-     */
109
-    public function initialize()
110
-    {
111
-        $this->_register_core_dependencies();
112
-        $this->_register_core_class_loaders();
113
-        $this->_register_core_aliases();
114
-    }
115
-
116
-
117
-    /**
118
-     * @singleton method used to instantiate class object
119
-     * @param ClassInterfaceCache|null $class_cache
120
-     * @return EE_Dependency_Map
121
-     */
122
-    public static function instance(ClassInterfaceCache $class_cache = null): EE_Dependency_Map
123
-    {
124
-        // check if class object is instantiated, and instantiated properly
125
-        if (
126
-            ! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
127
-            && $class_cache instanceof ClassInterfaceCache
128
-        ) {
129
-            EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
130
-        }
131
-        return EE_Dependency_Map::$_instance;
132
-    }
133
-
134
-
135
-    /**
136
-     * @param RequestInterface $request
137
-     */
138
-    public function setRequest(RequestInterface $request)
139
-    {
140
-        $this->request = $request;
141
-    }
142
-
143
-
144
-    /**
145
-     * @param LegacyRequestInterface $legacy_request
146
-     */
147
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
148
-    {
149
-        $this->legacy_request = $legacy_request;
150
-    }
151
-
152
-
153
-    /**
154
-     * @param ResponseInterface $response
155
-     */
156
-    public function setResponse(ResponseInterface $response)
157
-    {
158
-        $this->response = $response;
159
-    }
160
-
161
-
162
-    /**
163
-     * @param LoaderInterface $loader
164
-     */
165
-    public function setLoader(LoaderInterface $loader)
166
-    {
167
-        $this->loader = $loader;
168
-    }
169
-
170
-
171
-    /**
172
-     * @param string $class
173
-     * @param array  $dependencies
174
-     * @param int    $overwrite
175
-     * @return bool
176
-     */
177
-    public static function register_dependencies(
178
-        string $class,
179
-        array $dependencies,
180
-        int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
181
-    ): bool {
182
-        return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
183
-    }
184
-
185
-
186
-    /**
187
-     * Assigns an array of class names and corresponding load sources (new or cached)
188
-     * to the class specified by the first parameter.
189
-     * IMPORTANT !!!
190
-     * The order of elements in the incoming $dependencies array MUST match
191
-     * the order of the constructor parameters for the class in question.
192
-     * This is especially important when overriding any existing dependencies that are registered.
193
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
194
-     *
195
-     * @param string $class
196
-     * @param array  $dependencies
197
-     * @param int    $overwrite
198
-     * @return bool
199
-     */
200
-    public function registerDependencies(
201
-        string $class,
202
-        array $dependencies,
203
-        int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
204
-    ): bool {
205
-        $class      = trim($class, '\\');
206
-        $registered = false;
207
-        if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
208
-            EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
209
-        }
210
-        // we need to make sure that any aliases used when registering a dependency
211
-        // get resolved to the correct class name
212
-        foreach ($dependencies as $dependency => $load_source) {
213
-            $alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
214
-            if (
215
-                $overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
216
-                || ! isset(EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ])
217
-            ) {
218
-                unset($dependencies[ $dependency ]);
219
-                $dependencies[ $alias ] = $load_source;
220
-                $registered             = true;
221
-            }
222
-        }
223
-        // now add our two lists of dependencies together.
224
-        // using Union (+=) favours the arrays in precedence from left to right,
225
-        // so $dependencies is NOT overwritten because it is listed first
226
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
227
-        // Union is way faster than array_merge() but should be used with caution...
228
-        // especially with numerically indexed arrays
229
-        $dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
230
-        // now we need to ensure that the resulting dependencies
231
-        // array only has the entries that are required for the class
232
-        // so first count how many dependencies were originally registered for the class
233
-        $dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
234
-        // if that count is non-zero (meaning dependencies were already registered)
235
-        EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
236
-            // then truncate the  final array to match that count
237
-            ? array_slice($dependencies, 0, $dependency_count)
238
-            // otherwise just take the incoming array because nothing previously existed
239
-            : $dependencies;
240
-        return $registered;
241
-    }
242
-
243
-
244
-    /**
245
-     * @param string          $class_name
246
-     * @param callable|string $loader
247
-     * @param bool            $overwrite
248
-     * @return bool
249
-     * @throws DomainException
250
-     */
251
-    public static function register_class_loader(
252
-        string $class_name,
253
-        $loader = 'load_core',
254
-        bool $overwrite = false
255
-    ): bool {
256
-        return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader, $overwrite);
257
-    }
258
-
259
-
260
-    /**
261
-     * @param string $class_name
262
-     * @param Closure|string $loader
263
-     * @param bool   $overwrite
264
-     * @return bool
265
-     * @throws DomainException
266
-     */
267
-    public function registerClassLoader(string $class_name, $loader = 'load_core', bool $overwrite = false): bool
268
-    {
269
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
270
-            throw new DomainException(
271
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
272
-            );
273
-        }
274
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
275
-        if (
276
-            ! is_callable($loader)
277
-            && (
278
-                strpos($loader, 'load_') !== 0
279
-                || ! method_exists('EE_Registry', $loader)
280
-            )
281
-        ) {
282
-            throw new DomainException(
283
-                sprintf(
284
-                    esc_html__(
285
-                        '"%1$s" is not a valid loader method on EE_Registry.',
286
-                        'event_espresso'
287
-                    ),
288
-                    $loader
289
-                )
290
-            );
291
-        }
292
-        $class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
293
-        if ($overwrite || ! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
294
-            EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
295
-            return true;
296
-        }
297
-        return false;
298
-    }
299
-
300
-
301
-    /**
302
-     * @return array
303
-     */
304
-    public function dependency_map(): array
305
-    {
306
-        return $this->_dependency_map;
307
-    }
308
-
309
-
310
-    /**
311
-     * returns TRUE if dependency map contains a listing for the provided class name
312
-     *
313
-     * @param string $class_name
314
-     * @return boolean
315
-     */
316
-    public function has(string $class_name = ''): bool
317
-    {
318
-        // all legacy models have the same dependencies
319
-        if (strpos($class_name, 'EEM_') === 0) {
320
-            $class_name = 'LEGACY_MODELS';
321
-        }
322
-        return isset($this->_dependency_map[ $class_name ]);
323
-    }
324
-
325
-
326
-    /**
327
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
328
-     *
329
-     * @param string $class_name
330
-     * @param string $dependency
331
-     * @return bool
332
-     */
333
-    public function has_dependency_for_class(string $class_name = '', string $dependency = ''): bool
334
-    {
335
-        // all legacy models have the same dependencies
336
-        if (strpos($class_name, 'EEM_') === 0) {
337
-            $class_name = 'LEGACY_MODELS';
338
-        }
339
-        $dependency = $this->getFqnForAlias($dependency, $class_name);
340
-        return isset($this->_dependency_map[ $class_name ][ $dependency ]);
341
-    }
342
-
343
-
344
-    /**
345
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
346
-     *
347
-     * @param string $class_name
348
-     * @param string $dependency
349
-     * @return int
350
-     */
351
-    public function loading_strategy_for_class_dependency(string $class_name = '', string $dependency = ''): int
352
-    {
353
-        // all legacy models have the same dependencies
354
-        if (strpos($class_name, 'EEM_') === 0) {
355
-            $class_name = 'LEGACY_MODELS';
356
-        }
357
-        $dependency = $this->getFqnForAlias($dependency);
358
-        return $this->has_dependency_for_class($class_name, $dependency)
359
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
360
-            : EE_Dependency_Map::not_registered;
361
-    }
362
-
363
-
364
-    /**
365
-     * @param string $class_name
366
-     * @return string | Closure
367
-     */
368
-    public function class_loader(string $class_name)
369
-    {
370
-        // all legacy models use load_model()
371
-        if (strpos($class_name, 'EEM_') === 0) {
372
-            return 'load_model';
373
-        }
374
-        // EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
375
-        // perform strpos() first to avoid loading regex every time we load a class
376
-        if (
377
-            strpos($class_name, 'EE_CPT_') === 0
378
-            && preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
379
-        ) {
380
-            return 'load_core';
381
-        }
382
-        $class_name = $this->getFqnForAlias($class_name);
383
-        return $this->_class_loaders[ $class_name ] ?? '';
384
-    }
385
-
386
-
387
-    /**
388
-     * @return array
389
-     */
390
-    public function class_loaders(): array
391
-    {
392
-        return $this->_class_loaders;
393
-    }
394
-
395
-
396
-    /**
397
-     * adds an alias for a classname
398
-     *
399
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
400
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
401
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
402
-     * @throws InvalidAliasException
403
-     */
404
-    public function add_alias(string $fqcn, string $alias, string $for_class = '')
405
-    {
406
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
407
-    }
408
-
409
-
410
-    /**
411
-     * Returns TRUE if the provided fully qualified name IS an alias
412
-     * WHY?
413
-     * Because if a class is type hinting for a concretion,
414
-     * then why would we need to find another class to supply it?
415
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
416
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
417
-     * Don't go looking for some substitute.
418
-     * Whereas if a class is type hinting for an interface...
419
-     * then we need to find an actual class to use.
420
-     * So the interface IS the alias for some other FQN,
421
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
422
-     * represents some other class.
423
-     *
424
-     * @param string $fqn
425
-     * @param string $for_class
426
-     * @return bool
427
-     */
428
-    public function isAlias(string $fqn = '', string $for_class = ''): bool
429
-    {
430
-        return $this->class_cache->isAlias($fqn, $for_class);
431
-    }
432
-
433
-
434
-    /**
435
-     * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
436
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
437
-     *  for example:
438
-     *      if the following two entries were added to the _aliases array:
439
-     *          array(
440
-     *              'interface_alias'           => 'some\namespace\interface'
441
-     *              'some\namespace\interface'  => 'some\namespace\classname'
442
-     *          )
443
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
444
-     *      to load an instance of 'some\namespace\classname'
445
-     *
446
-     * @param string $alias
447
-     * @param string $for_class
448
-     * @return string
449
-     */
450
-    public function getFqnForAlias(string $alias = '', string $for_class = ''): string
451
-    {
452
-        return $this->class_cache->getFqnForAlias($alias, $for_class);
453
-    }
454
-
455
-
456
-    /**
457
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
458
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
459
-     * This is done by using the following class constants:
460
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
461
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
462
-     */
463
-    protected function _register_core_dependencies()
464
-    {
465
-        $this->_dependency_map = [
466
-            'EE_Admin'                                                                                                    => [
467
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
468
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
469
-            ],
470
-            'EE_Request_Handler'                                                                                          => [
471
-                'EventEspresso\core\services\request\Request'  => EE_Dependency_Map::load_from_cache,
472
-                'EventEspresso\core\services\request\Response' => EE_Dependency_Map::load_from_cache,
473
-            ],
474
-            'EE_System'                                                                                                   => [
475
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
476
-                'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
477
-                'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
478
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
479
-                'EventEspresso\core\services\routing\Router'  => EE_Dependency_Map::load_from_cache,
480
-            ],
481
-            'EE_Session'                                                                                                  => [
482
-                'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
483
-                'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
484
-                'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
485
-                'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
486
-                'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
487
-            ],
488
-            'EE_Cart'                                                                                                     => [
489
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
490
-            ],
491
-            'EE_Messenger_Collection_Loader'                                                                              => [
492
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
493
-            ],
494
-            'EE_Message_Type_Collection_Loader'                                                                           => [
495
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
496
-            ],
497
-            'EE_Message_Resource_Manager'                                                                                 => [
498
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
499
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
500
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
501
-            ],
502
-            'EE_Message_Factory'                                                                                          => [
503
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
504
-            ],
505
-            'EE_messages'                                                                                                 => [
506
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
507
-            ],
508
-            'EE_Messages_Generator'                                                                                       => [
509
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
510
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
511
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
512
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
513
-            ],
514
-            'EE_Messages_Processor'                                                                                       => [
515
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
516
-            ],
517
-            'EE_Messages_Queue'                                                                                           => [
518
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
519
-            ],
520
-            'EE_Messages_Template_Defaults'                                                                               => [
521
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
522
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
523
-            ],
524
-            'EE_Message_To_Generate_From_Request'                                                                         => [
525
-                'EE_Message_Resource_Manager'                 => EE_Dependency_Map::load_from_cache,
526
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
527
-            ],
528
-            'EventEspresso\core\services\commands\CommandBus'                                                             => [
529
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
530
-            ],
531
-            'EventEspresso\services\commands\CommandHandler'                                                              => [
532
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
533
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
534
-            ],
535
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => [
536
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
537
-            ],
538
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => [
539
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
540
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
541
-            ],
542
-            'EventEspresso\core\services\commands\CommandFactory'                                                         => [
543
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
544
-            ],
545
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => [
546
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
547
-            ],
548
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => [
549
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
550
-            ],
551
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => [
552
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
553
-            ],
554
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => [
555
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
556
-            ],
557
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
558
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
559
-            ],
560
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
561
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
562
-            ],
563
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
564
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
565
-            ],
566
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
567
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
568
-            ],
569
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
570
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
571
-            ],
572
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
573
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
574
-            ],
575
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => [
576
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
577
-            ],
578
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
579
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
580
-            ],
581
-            'EventEspresso\core\services\database\TableManager'                                                           => [
582
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
583
-            ],
584
-            'EE_Data_Migration_Class_Base'                                                                                => [
585
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
586
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
587
-            ],
588
-            'EE_DMS_Core_4_1_0'                                                                                           => [
589
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
590
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
591
-            ],
592
-            'EE_DMS_Core_4_2_0'                                                                                           => [
593
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
594
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
595
-            ],
596
-            'EE_DMS_Core_4_3_0'                                                                                           => [
597
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
598
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
599
-            ],
600
-            'EE_DMS_Core_4_4_0'                                                                                           => [
601
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
602
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
603
-            ],
604
-            'EE_DMS_Core_4_5_0'                                                                                           => [
605
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
606
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
607
-            ],
608
-            'EE_DMS_Core_4_6_0'                                                                                           => [
609
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
610
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
611
-            ],
612
-            'EE_DMS_Core_4_7_0'                                                                                           => [
613
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
614
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
615
-            ],
616
-            'EE_DMS_Core_4_8_0'                                                                                           => [
617
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
618
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
619
-            ],
620
-            'EE_DMS_Core_4_9_0'                                                                                           => [
621
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
622
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
623
-            ],
624
-            'EE_DMS_Core_4_10_0'                                                                                          => [
625
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
626
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
627
-                'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
628
-            ],
629
-            'EE_DMS_Core_4_11_0'                                                                                          => [
630
-                'EE_DMS_Core_4_10_0'                                 => EE_Dependency_Map::load_from_cache,
631
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
632
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
633
-            ],
634
-            'EE_DMS_Core_4_12_0'                                                                                          => [
635
-                'EE_DMS_Core_4_11_0'                                 => EE_Dependency_Map::load_from_cache,
636
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
637
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
638
-            ],
639
-            'EventEspresso\core\services\assets\I18nRegistry'                                                             => [
640
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
641
-            ],
642
-            'EventEspresso\core\services\assets\Registry'                                                                 => [
643
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
644
-                'EventEspresso\core\services\assets\AssetManifest'   => EE_Dependency_Map::load_from_cache,
645
-            ],
646
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => [
647
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
648
-            ],
649
-            'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => [
650
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
651
-            ],
652
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => [
653
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
654
-            ],
655
-            'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => [
656
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
657
-            ],
658
-            'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => [
659
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
660
-            ],
661
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => [
662
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
663
-            ],
664
-            'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => [
665
-                'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
666
-            ],
667
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => [
668
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
669
-            ],
670
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => [
671
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
672
-            ],
673
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => [
674
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
675
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
676
-            ],
677
-            'EventEspresso\core\domain\values\EmailAddress'                                                               => [
678
-                null,
679
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
680
-            ],
681
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => [
682
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
683
-            ],
684
-            'LEGACY_MODELS'                                                                                               => [
685
-                null,
686
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
687
-            ],
688
-            'EE_Module_Request_Router'                                                                                    => [
689
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
690
-            ],
691
-            'EE_Registration_Processor'                                                                                   => [
692
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
693
-            ],
694
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => [
695
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
696
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
697
-            ],
698
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => [
699
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
700
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
701
-            ],
702
-            'EventEspresso\modules\ticket_selector\DisplayTicketSelector'                                                 => [
703
-                'EventEspresso\core\domain\entities\users\CurrentUser' => EE_Dependency_Map::load_from_cache,
704
-                'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
705
-                'EE_Ticket_Selector_Config'                            => EE_Dependency_Map::load_from_cache,
706
-            ],
707
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => [
708
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
709
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
710
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
711
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
712
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
713
-            ],
714
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => [
715
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
716
-            ],
717
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => [
718
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
719
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
720
-            ],
721
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => [
722
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
723
-            ],
724
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => [
725
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
726
-            ],
727
-            'EE_CPT_Strategy'                                                                                             => [
728
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
729
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
730
-            ],
731
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => [
732
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
733
-            ],
734
-            'EventEspresso\core\CPTs\CptQueryModifier'                                                                    => [
735
-                null,
736
-                null,
737
-                null,
738
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
739
-                'EventEspresso\core\services\request\Request'     => EE_Dependency_Map::load_from_cache,
740
-                'EventEspresso\core\services\loaders\Loader'      => EE_Dependency_Map::load_from_cache,
741
-            ],
742
-            'EventEspresso\core\services\dependencies\DependencyResolver'                                                 => [
743
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
744
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
745
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
746
-            ],
747
-            'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                               => [
748
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
749
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
750
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
751
-            ],
752
-            'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                          => [
753
-                'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
754
-                'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
755
-            ],
756
-            'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                          => [
757
-                'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
758
-                'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
759
-            ],
760
-            'EE_URL_Validation_Strategy'                                                                                  => [
761
-                null,
762
-                null,
763
-                'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache,
764
-            ],
765
-            'EventEspresso\core\services\request\files\FilesDataHandler'                                                  => [
766
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
767
-            ],
768
-            'EventEspressoBatchRequest\BatchRequestProcessor'                                                             => [
769
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
770
-            ],
771
-            'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                => [
772
-                'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
773
-                'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
774
-                'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
775
-                null,
776
-            ],
777
-            'EventEspresso\core\services\routing\RouteHandler'                                                            => [
778
-                'EventEspresso\core\services\json\JsonDataNodeHandler' => EE_Dependency_Map::load_from_cache,
779
-                'EventEspresso\core\services\loaders\Loader'           => EE_Dependency_Map::load_from_cache,
780
-                'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
781
-                'EventEspresso\core\services\routing\RouteCollection'  => EE_Dependency_Map::load_from_cache,
782
-            ],
783
-            'EventEspresso\core\services\json\JsonDataNodeHandler'                                                        => [
784
-                'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
785
-            ],
786
-            'EventEspresso\core\services\routing\Router'                                                                  => [
787
-                'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
788
-                'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
789
-                'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
790
-            ],
791
-            'EventEspresso\core\services\assets\AssetManifest'                                                            => [
792
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
793
-            ],
794
-            'EventEspresso\core\services\assets\AssetManifestFactory'                                                     => [
795
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
796
-            ],
797
-            'EventEspresso\core\services\assets\BaristaFactory'                                                           => [
798
-                'EventEspresso\core\services\assets\AssetManifestFactory' => EE_Dependency_Map::load_from_cache,
799
-                'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
800
-            ],
801
-            'EventEspresso\core\domain\services\capabilities\FeatureFlags'                                                => [
802
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
803
-                'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
804
-            ],
805
-            'EventEspresso\core\services\addon\AddonManager'                                                              => [
806
-                'EventEspresso\core\services\addon\AddonCollection'              => EE_Dependency_Map::load_from_cache,
807
-                'EventEspresso\core\Psr4Autoloader'                              => EE_Dependency_Map::load_from_cache,
808
-                'EventEspresso\core\services\addon\api\v1\RegisterAddon'         => EE_Dependency_Map::load_from_cache,
809
-                'EventEspresso\core\services\addon\api\IncompatibleAddonHandler' => EE_Dependency_Map::load_from_cache,
810
-                'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'  => EE_Dependency_Map::load_from_cache,
811
-            ],
812
-            'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'                                               => [
813
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
814
-            ],
815
-            'EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion'                                                  => [
816
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
817
-            ],
818
-            'EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'                                                  => [
819
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
820
-            ],
821
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'                                        => [
822
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
823
-                'EEM_Event'                                                   => EE_Dependency_Map::load_from_cache,
824
-                'EEM_Datetime'                                                => EE_Dependency_Map::load_from_cache,
825
-                'EEM_Registration'                                            => EE_Dependency_Map::load_from_cache,
826
-            ],
827
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'                                        => [
828
-                'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
829
-            ],
830
-            'EventEspresso\core\services\request\CurrentPage'                                                             => [
831
-                'EE_CPT_Strategy'                             => EE_Dependency_Map::load_from_cache,
832
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
833
-            ],
834
-            'EventEspresso\core\services\shortcodes\LegacyShortcodesManager'                                              => [
835
-                'EE_Registry'                                     => EE_Dependency_Map::load_from_cache,
836
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
837
-            ],
838
-            'EventEspresso\core\services\shortcodes\ShortcodesManager'                                                    => [
839
-                'EventEspresso\core\services\shortcodes\LegacyShortcodesManager' => EE_Dependency_Map::load_from_cache,
840
-                'EventEspresso\core\services\request\CurrentPage'                => EE_Dependency_Map::load_from_cache,
841
-            ],
842
-            'EventEspresso\core\domain\entities\users\CurrentUser'                                                        => [
843
-                'EventEspresso\core\domain\entities\users\EventManagers' => EE_Dependency_Map::load_from_cache,
844
-            ],
845
-            'EventEspresso\core\services\form\meta\InputTypes'                                                            => [
846
-                'EventEspresso\core\services\form\meta\inputs\Block'    => EE_Dependency_Map::load_from_cache,
847
-                'EventEspresso\core\services\form\meta\inputs\Button'   => EE_Dependency_Map::load_from_cache,
848
-                'EventEspresso\core\services\form\meta\inputs\DateTime' => EE_Dependency_Map::load_from_cache,
849
-                'EventEspresso\core\services\form\meta\inputs\Input'    => EE_Dependency_Map::load_from_cache,
850
-                'EventEspresso\core\services\form\meta\inputs\Number'   => EE_Dependency_Map::load_from_cache,
851
-                'EventEspresso\core\services\form\meta\inputs\Phone'    => EE_Dependency_Map::load_from_cache,
852
-                'EventEspresso\core\services\form\meta\inputs\Select'   => EE_Dependency_Map::load_from_cache,
853
-                'EventEspresso\core\services\form\meta\inputs\Text'     => EE_Dependency_Map::load_from_cache,
854
-            ],
855
-            'EventEspresso\core\domain\services\registration\form\v1\RegFormDependencyHandler'                            => [
856
-                'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
857
-            ],
858
-            'EventEspresso\core\services\calculators\LineItemCalculator'                                                  => [
859
-                'EventEspresso\core\services\helpers\DecimalValues' => EE_Dependency_Map::load_from_cache,
860
-            ],
861
-            'EventEspresso\core\services\helpers\DecimalValues'                                                           => [
862
-                'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
863
-            ],
864
-        ];
865
-    }
866
-
867
-
868
-    /**
869
-     * Registers how core classes are loaded.
870
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
871
-     *        'EE_Request_Handler' => 'load_core'
872
-     *        'EE_Messages_Queue'  => 'load_lib'
873
-     *        'EEH_Debug_Tools'    => 'load_helper'
874
-     * or, if greater control is required, by providing a custom closure. For example:
875
-     *        'Some_Class' => function () {
876
-     *            return new Some_Class();
877
-     *        },
878
-     * This is required for instantiating dependencies
879
-     * where an interface has been type hinted in a class constructor. For example:
880
-     *        'Required_Interface' => function () {
881
-     *            return new A_Class_That_Implements_Required_Interface();
882
-     *        },
883
-     */
884
-    protected function _register_core_class_loaders()
885
-    {
886
-        $this->_class_loaders = [
887
-            // load_core
888
-            'EE_Dependency_Map'                            => function () {
889
-                return $this;
890
-            },
891
-            'EE_Capabilities'                              => 'load_core',
892
-            'EE_Encryption'                                => 'load_core',
893
-            'EE_Front_Controller'                          => 'load_core',
894
-            'EE_Module_Request_Router'                     => 'load_core',
895
-            'EE_Registry'                                  => 'load_core',
896
-            'EE_Request'                                   => function () {
897
-                return $this->legacy_request;
898
-            },
899
-            'EventEspresso\core\services\request\Request'  => function () {
900
-                return $this->request;
901
-            },
902
-            'EventEspresso\core\services\request\Response' => function () {
903
-                return $this->response;
904
-            },
905
-            'EE_Base'                                      => 'load_core',
906
-            'EE_Request_Handler'                           => 'load_core',
907
-            'EE_Session'                                   => 'load_core',
908
-            'EE_Cron_Tasks'                                => 'load_core',
909
-            'EE_System'                                    => 'load_core',
910
-            'EE_Maintenance_Mode'                          => 'load_core',
911
-            'EE_Register_CPTs'                             => 'load_core',
912
-            'EE_Admin'                                     => 'load_core',
913
-            'EE_CPT_Strategy'                              => 'load_core',
914
-            // load_class
915
-            'EE_Registration_Processor'                    => 'load_class',
916
-            // load_lib
917
-            'EE_Message_Resource_Manager'                  => 'load_lib',
918
-            'EE_Message_Type_Collection'                   => 'load_lib',
919
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
920
-            'EE_Messenger_Collection'                      => 'load_lib',
921
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
922
-            'EE_Messages_Processor'                        => 'load_lib',
923
-            'EE_Message_Repository'                        => 'load_lib',
924
-            'EE_Messages_Queue'                            => 'load_lib',
925
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
926
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
927
-            'EE_Payment_Method_Manager'                    => 'load_lib',
928
-            'EE_DMS_Core_4_1_0'                            => 'load_dms',
929
-            'EE_DMS_Core_4_2_0'                            => 'load_dms',
930
-            'EE_DMS_Core_4_3_0'                            => 'load_dms',
931
-            'EE_DMS_Core_4_5_0'                            => 'load_dms',
932
-            'EE_DMS_Core_4_6_0'                            => 'load_dms',
933
-            'EE_DMS_Core_4_7_0'                            => 'load_dms',
934
-            'EE_DMS_Core_4_8_0'                            => 'load_dms',
935
-            'EE_DMS_Core_4_9_0'                            => 'load_dms',
936
-            'EE_DMS_Core_4_10_0'                           => 'load_dms',
937
-            'EE_DMS_Core_4_11_0'                           => 'load_dms',
938
-            'EE_DMS_Core_4_12_0'                           => 'load_dms',
939
-            'EE_Messages_Generator'                        => static function () {
940
-                return EE_Registry::instance()->load_lib(
941
-                    'Messages_Generator',
942
-                    [],
943
-                    false,
944
-                    false
945
-                );
946
-            },
947
-            'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
948
-                return EE_Registry::instance()->load_lib(
949
-                    'Messages_Template_Defaults',
950
-                    $arguments,
951
-                    false,
952
-                    false
953
-                );
954
-            },
955
-            // load_helper
956
-            'EEH_Parse_Shortcodes'                         => static function () {
957
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
958
-                    return new EEH_Parse_Shortcodes();
959
-                }
960
-                return null;
961
-            },
962
-            'EE_Template_Config'                           => static function () {
963
-                return EE_Config::instance()->template_settings;
964
-            },
965
-            'EE_Currency_Config'                           => static function () {
966
-                return EE_Currency_Config::getCurrencyConfig();
967
-            },
968
-            'EE_Registration_Config'                       => static function () {
969
-                return EE_Config::instance()->registration;
970
-            },
971
-            'EE_Core_Config'                               => static function () {
972
-                return EE_Config::instance()->core;
973
-            },
974
-            'EventEspresso\core\services\loaders\Loader'   => static function () {
975
-                return LoaderFactory::getLoader();
976
-            },
977
-            'EE_Network_Config'                            => static function () {
978
-                return EE_Network_Config::instance();
979
-            },
980
-            'EE_Config'                                    => static function () {
981
-                return EE_Config::instance();
982
-            },
983
-            'EventEspresso\core\domain\Domain'             => static function () {
984
-                return DomainFactory::getEventEspressoCoreDomain();
985
-            },
986
-            'EE_Admin_Config'                              => static function () {
987
-                return EE_Config::instance()->admin;
988
-            },
989
-            'EE_Organization_Config'                       => static function () {
990
-                return EE_Config::instance()->organization;
991
-            },
992
-            'EE_Network_Core_Config'                       => static function () {
993
-                return EE_Network_Config::instance()->core;
994
-            },
995
-            'EE_Environment_Config'                        => static function () {
996
-                return EE_Config::instance()->environment;
997
-            },
998
-            'EED_Core_Rest_Api'                            => static function () {
999
-                return EED_Core_Rest_Api::instance();
1000
-            },
1001
-            'WP_REST_Server'                               => static function () {
1002
-                return rest_get_server();
1003
-            },
1004
-            'EventEspresso\core\Psr4Autoloader'            => static function () {
1005
-                return EE_Psr4AutoloaderInit::psr4_loader();
1006
-            },
1007
-            'EE_Ticket_Selector_Config'                    => function () {
1008
-                return EE_Config::instance()->template_settings->EED_Ticket_Selector;
1009
-            },
1010
-        ];
1011
-    }
1012
-
1013
-
1014
-    /**
1015
-     * can be used for supplying alternate names for classes,
1016
-     * or for connecting interface names to instantiable classes
1017
-     *
1018
-     * @throws InvalidAliasException
1019
-     */
1020
-    protected function _register_core_aliases()
1021
-    {
1022
-        $aliases = [
1023
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1024
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1025
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1026
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1027
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1028
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1029
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1030
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1031
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1032
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1033
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1034
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1035
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1036
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1037
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1038
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1039
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1040
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1041
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1042
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1043
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1044
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1045
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1046
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1047
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1048
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1049
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1050
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1051
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1052
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1053
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1054
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1055
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1056
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1057
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1058
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1059
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1060
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
1061
-            'EventEspresso\core\services\assets\AssetManifestInterface'                    => 'EventEspresso\core\services\assets\AssetManifest',
1062
-        ];
1063
-        foreach ($aliases as $alias => $fqn) {
1064
-            if (is_array($fqn)) {
1065
-                foreach ($fqn as $class => $for_class) {
1066
-                    $this->class_cache->addAlias($class, $alias, $for_class);
1067
-                }
1068
-                continue;
1069
-            }
1070
-            $this->class_cache->addAlias($fqn, $alias);
1071
-        }
1072
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1073
-            $this->class_cache->addAlias(
1074
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1075
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
1076
-            );
1077
-        }
1078
-    }
1079
-
1080
-
1081
-    public function debug($for_class = '')
1082
-    {
1083
-        if (method_exists($this->class_cache, 'debug')) {
1084
-            $this->class_cache->debug($for_class);
1085
-        }
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1091
-     * request Primarily used by unit tests.
1092
-     */
1093
-    public function reset()
1094
-    {
1095
-        $this->_register_core_class_loaders();
1096
-        $this->_register_core_dependencies();
1097
-    }
1098
-
1099
-
1100
-    /**
1101
-     * PLZ NOTE: a better name for this method would be is_alias()
1102
-     * because it returns TRUE if the provided fully qualified name IS an alias
1103
-     * WHY?
1104
-     * Because if a class is type hinting for a concretion,
1105
-     * then why would we need to find another class to supply it?
1106
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1107
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1108
-     * Don't go looking for some substitute.
1109
-     * Whereas if a class is type hinting for an interface...
1110
-     * then we need to find an actual class to use.
1111
-     * So the interface IS the alias for some other FQN,
1112
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1113
-     * represents some other class.
1114
-     *
1115
-     * @param string $fqn
1116
-     * @param string $for_class
1117
-     * @return bool
1118
-     * @deprecated 4.9.62.p
1119
-     */
1120
-    public function has_alias(string $fqn = '', string $for_class = ''): bool
1121
-    {
1122
-        return $this->isAlias($fqn, $for_class);
1123
-    }
1124
-
1125
-
1126
-    /**
1127
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1128
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1129
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
1130
-     *  for example:
1131
-     *      if the following two entries were added to the _aliases array:
1132
-     *          array(
1133
-     *              'interface_alias'           => 'some\namespace\interface'
1134
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1135
-     *          )
1136
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1137
-     *      to load an instance of 'some\namespace\classname'
1138
-     *
1139
-     * @param string $alias
1140
-     * @param string $for_class
1141
-     * @return string
1142
-     * @deprecated 4.9.62.p
1143
-     */
1144
-    public function get_alias(string $alias = '', string $for_class = ''): string
1145
-    {
1146
-        return $this->getFqnForAlias($alias, $for_class);
1147
-    }
23
+	/**
24
+	 * This means that the requested class dependency is not present in the dependency map
25
+	 */
26
+	const not_registered = 0;
27
+
28
+	/**
29
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
30
+	 */
31
+	const load_new_object = 1;
32
+
33
+	/**
34
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
35
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
36
+	 */
37
+	const load_from_cache = 2;
38
+
39
+	/**
40
+	 * When registering a dependency,
41
+	 * this indicates to keep any existing dependencies that already exist,
42
+	 * and simply discard any new dependencies declared in the incoming data
43
+	 */
44
+	const KEEP_EXISTING_DEPENDENCIES = 0;
45
+
46
+	/**
47
+	 * When registering a dependency,
48
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
49
+	 */
50
+	const OVERWRITE_DEPENDENCIES = 1;
51
+
52
+	/**
53
+	 * @type EE_Dependency_Map $_instance
54
+	 */
55
+	protected static $_instance;
56
+
57
+	/**
58
+	 * @var ClassInterfaceCache $class_cache
59
+	 */
60
+	private $class_cache;
61
+
62
+	/**
63
+	 * @type RequestInterface $request
64
+	 */
65
+	protected $request;
66
+
67
+	/**
68
+	 * @type LegacyRequestInterface $legacy_request
69
+	 */
70
+	protected $legacy_request;
71
+
72
+	/**
73
+	 * @type ResponseInterface $response
74
+	 */
75
+	protected $response;
76
+
77
+	/**
78
+	 * @type LoaderInterface $loader
79
+	 */
80
+	protected $loader;
81
+
82
+	/**
83
+	 * @type array $_dependency_map
84
+	 */
85
+	protected $_dependency_map = [];
86
+
87
+	/**
88
+	 * @type array $_class_loaders
89
+	 */
90
+	protected $_class_loaders = [];
91
+
92
+
93
+	/**
94
+	 * EE_Dependency_Map constructor.
95
+	 *
96
+	 * @param ClassInterfaceCache $class_cache
97
+	 */
98
+	protected function __construct(ClassInterfaceCache $class_cache)
99
+	{
100
+		$this->class_cache = $class_cache;
101
+		do_action('EE_Dependency_Map____construct', $this);
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return void
107
+	 * @throws InvalidAliasException
108
+	 */
109
+	public function initialize()
110
+	{
111
+		$this->_register_core_dependencies();
112
+		$this->_register_core_class_loaders();
113
+		$this->_register_core_aliases();
114
+	}
115
+
116
+
117
+	/**
118
+	 * @singleton method used to instantiate class object
119
+	 * @param ClassInterfaceCache|null $class_cache
120
+	 * @return EE_Dependency_Map
121
+	 */
122
+	public static function instance(ClassInterfaceCache $class_cache = null): EE_Dependency_Map
123
+	{
124
+		// check if class object is instantiated, and instantiated properly
125
+		if (
126
+			! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
127
+			&& $class_cache instanceof ClassInterfaceCache
128
+		) {
129
+			EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
130
+		}
131
+		return EE_Dependency_Map::$_instance;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param RequestInterface $request
137
+	 */
138
+	public function setRequest(RequestInterface $request)
139
+	{
140
+		$this->request = $request;
141
+	}
142
+
143
+
144
+	/**
145
+	 * @param LegacyRequestInterface $legacy_request
146
+	 */
147
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
148
+	{
149
+		$this->legacy_request = $legacy_request;
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param ResponseInterface $response
155
+	 */
156
+	public function setResponse(ResponseInterface $response)
157
+	{
158
+		$this->response = $response;
159
+	}
160
+
161
+
162
+	/**
163
+	 * @param LoaderInterface $loader
164
+	 */
165
+	public function setLoader(LoaderInterface $loader)
166
+	{
167
+		$this->loader = $loader;
168
+	}
169
+
170
+
171
+	/**
172
+	 * @param string $class
173
+	 * @param array  $dependencies
174
+	 * @param int    $overwrite
175
+	 * @return bool
176
+	 */
177
+	public static function register_dependencies(
178
+		string $class,
179
+		array $dependencies,
180
+		int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
181
+	): bool {
182
+		return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
183
+	}
184
+
185
+
186
+	/**
187
+	 * Assigns an array of class names and corresponding load sources (new or cached)
188
+	 * to the class specified by the first parameter.
189
+	 * IMPORTANT !!!
190
+	 * The order of elements in the incoming $dependencies array MUST match
191
+	 * the order of the constructor parameters for the class in question.
192
+	 * This is especially important when overriding any existing dependencies that are registered.
193
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
194
+	 *
195
+	 * @param string $class
196
+	 * @param array  $dependencies
197
+	 * @param int    $overwrite
198
+	 * @return bool
199
+	 */
200
+	public function registerDependencies(
201
+		string $class,
202
+		array $dependencies,
203
+		int $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
204
+	): bool {
205
+		$class      = trim($class, '\\');
206
+		$registered = false;
207
+		if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
208
+			EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
209
+		}
210
+		// we need to make sure that any aliases used when registering a dependency
211
+		// get resolved to the correct class name
212
+		foreach ($dependencies as $dependency => $load_source) {
213
+			$alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
214
+			if (
215
+				$overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
216
+				|| ! isset(EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ])
217
+			) {
218
+				unset($dependencies[ $dependency ]);
219
+				$dependencies[ $alias ] = $load_source;
220
+				$registered             = true;
221
+			}
222
+		}
223
+		// now add our two lists of dependencies together.
224
+		// using Union (+=) favours the arrays in precedence from left to right,
225
+		// so $dependencies is NOT overwritten because it is listed first
226
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
227
+		// Union is way faster than array_merge() but should be used with caution...
228
+		// especially with numerically indexed arrays
229
+		$dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
230
+		// now we need to ensure that the resulting dependencies
231
+		// array only has the entries that are required for the class
232
+		// so first count how many dependencies were originally registered for the class
233
+		$dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
234
+		// if that count is non-zero (meaning dependencies were already registered)
235
+		EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
236
+			// then truncate the  final array to match that count
237
+			? array_slice($dependencies, 0, $dependency_count)
238
+			// otherwise just take the incoming array because nothing previously existed
239
+			: $dependencies;
240
+		return $registered;
241
+	}
242
+
243
+
244
+	/**
245
+	 * @param string          $class_name
246
+	 * @param callable|string $loader
247
+	 * @param bool            $overwrite
248
+	 * @return bool
249
+	 * @throws DomainException
250
+	 */
251
+	public static function register_class_loader(
252
+		string $class_name,
253
+		$loader = 'load_core',
254
+		bool $overwrite = false
255
+	): bool {
256
+		return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader, $overwrite);
257
+	}
258
+
259
+
260
+	/**
261
+	 * @param string $class_name
262
+	 * @param Closure|string $loader
263
+	 * @param bool   $overwrite
264
+	 * @return bool
265
+	 * @throws DomainException
266
+	 */
267
+	public function registerClassLoader(string $class_name, $loader = 'load_core', bool $overwrite = false): bool
268
+	{
269
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
270
+			throw new DomainException(
271
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
272
+			);
273
+		}
274
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
275
+		if (
276
+			! is_callable($loader)
277
+			&& (
278
+				strpos($loader, 'load_') !== 0
279
+				|| ! method_exists('EE_Registry', $loader)
280
+			)
281
+		) {
282
+			throw new DomainException(
283
+				sprintf(
284
+					esc_html__(
285
+						'"%1$s" is not a valid loader method on EE_Registry.',
286
+						'event_espresso'
287
+					),
288
+					$loader
289
+				)
290
+			);
291
+		}
292
+		$class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
293
+		if ($overwrite || ! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
294
+			EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
295
+			return true;
296
+		}
297
+		return false;
298
+	}
299
+
300
+
301
+	/**
302
+	 * @return array
303
+	 */
304
+	public function dependency_map(): array
305
+	{
306
+		return $this->_dependency_map;
307
+	}
308
+
309
+
310
+	/**
311
+	 * returns TRUE if dependency map contains a listing for the provided class name
312
+	 *
313
+	 * @param string $class_name
314
+	 * @return boolean
315
+	 */
316
+	public function has(string $class_name = ''): bool
317
+	{
318
+		// all legacy models have the same dependencies
319
+		if (strpos($class_name, 'EEM_') === 0) {
320
+			$class_name = 'LEGACY_MODELS';
321
+		}
322
+		return isset($this->_dependency_map[ $class_name ]);
323
+	}
324
+
325
+
326
+	/**
327
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
328
+	 *
329
+	 * @param string $class_name
330
+	 * @param string $dependency
331
+	 * @return bool
332
+	 */
333
+	public function has_dependency_for_class(string $class_name = '', string $dependency = ''): bool
334
+	{
335
+		// all legacy models have the same dependencies
336
+		if (strpos($class_name, 'EEM_') === 0) {
337
+			$class_name = 'LEGACY_MODELS';
338
+		}
339
+		$dependency = $this->getFqnForAlias($dependency, $class_name);
340
+		return isset($this->_dependency_map[ $class_name ][ $dependency ]);
341
+	}
342
+
343
+
344
+	/**
345
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
346
+	 *
347
+	 * @param string $class_name
348
+	 * @param string $dependency
349
+	 * @return int
350
+	 */
351
+	public function loading_strategy_for_class_dependency(string $class_name = '', string $dependency = ''): int
352
+	{
353
+		// all legacy models have the same dependencies
354
+		if (strpos($class_name, 'EEM_') === 0) {
355
+			$class_name = 'LEGACY_MODELS';
356
+		}
357
+		$dependency = $this->getFqnForAlias($dependency);
358
+		return $this->has_dependency_for_class($class_name, $dependency)
359
+			? $this->_dependency_map[ $class_name ][ $dependency ]
360
+			: EE_Dependency_Map::not_registered;
361
+	}
362
+
363
+
364
+	/**
365
+	 * @param string $class_name
366
+	 * @return string | Closure
367
+	 */
368
+	public function class_loader(string $class_name)
369
+	{
370
+		// all legacy models use load_model()
371
+		if (strpos($class_name, 'EEM_') === 0) {
372
+			return 'load_model';
373
+		}
374
+		// EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
375
+		// perform strpos() first to avoid loading regex every time we load a class
376
+		if (
377
+			strpos($class_name, 'EE_CPT_') === 0
378
+			&& preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
379
+		) {
380
+			return 'load_core';
381
+		}
382
+		$class_name = $this->getFqnForAlias($class_name);
383
+		return $this->_class_loaders[ $class_name ] ?? '';
384
+	}
385
+
386
+
387
+	/**
388
+	 * @return array
389
+	 */
390
+	public function class_loaders(): array
391
+	{
392
+		return $this->_class_loaders;
393
+	}
394
+
395
+
396
+	/**
397
+	 * adds an alias for a classname
398
+	 *
399
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
400
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
401
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
402
+	 * @throws InvalidAliasException
403
+	 */
404
+	public function add_alias(string $fqcn, string $alias, string $for_class = '')
405
+	{
406
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
407
+	}
408
+
409
+
410
+	/**
411
+	 * Returns TRUE if the provided fully qualified name IS an alias
412
+	 * WHY?
413
+	 * Because if a class is type hinting for a concretion,
414
+	 * then why would we need to find another class to supply it?
415
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
416
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
417
+	 * Don't go looking for some substitute.
418
+	 * Whereas if a class is type hinting for an interface...
419
+	 * then we need to find an actual class to use.
420
+	 * So the interface IS the alias for some other FQN,
421
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
422
+	 * represents some other class.
423
+	 *
424
+	 * @param string $fqn
425
+	 * @param string $for_class
426
+	 * @return bool
427
+	 */
428
+	public function isAlias(string $fqn = '', string $for_class = ''): bool
429
+	{
430
+		return $this->class_cache->isAlias($fqn, $for_class);
431
+	}
432
+
433
+
434
+	/**
435
+	 * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
436
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
437
+	 *  for example:
438
+	 *      if the following two entries were added to the _aliases array:
439
+	 *          array(
440
+	 *              'interface_alias'           => 'some\namespace\interface'
441
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
442
+	 *          )
443
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
444
+	 *      to load an instance of 'some\namespace\classname'
445
+	 *
446
+	 * @param string $alias
447
+	 * @param string $for_class
448
+	 * @return string
449
+	 */
450
+	public function getFqnForAlias(string $alias = '', string $for_class = ''): string
451
+	{
452
+		return $this->class_cache->getFqnForAlias($alias, $for_class);
453
+	}
454
+
455
+
456
+	/**
457
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
458
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
459
+	 * This is done by using the following class constants:
460
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
461
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
462
+	 */
463
+	protected function _register_core_dependencies()
464
+	{
465
+		$this->_dependency_map = [
466
+			'EE_Admin'                                                                                                    => [
467
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
468
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
469
+			],
470
+			'EE_Request_Handler'                                                                                          => [
471
+				'EventEspresso\core\services\request\Request'  => EE_Dependency_Map::load_from_cache,
472
+				'EventEspresso\core\services\request\Response' => EE_Dependency_Map::load_from_cache,
473
+			],
474
+			'EE_System'                                                                                                   => [
475
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
476
+				'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
477
+				'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
478
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
479
+				'EventEspresso\core\services\routing\Router'  => EE_Dependency_Map::load_from_cache,
480
+			],
481
+			'EE_Session'                                                                                                  => [
482
+				'EventEspresso\core\services\cache\TransientCacheStorage'  => EE_Dependency_Map::load_from_cache,
483
+				'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache,
484
+				'EventEspresso\core\services\request\Request'              => EE_Dependency_Map::load_from_cache,
485
+				'EventEspresso\core\services\session\SessionStartHandler'  => EE_Dependency_Map::load_from_cache,
486
+				'EE_Encryption'                                            => EE_Dependency_Map::load_from_cache,
487
+			],
488
+			'EE_Cart'                                                                                                     => [
489
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
490
+			],
491
+			'EE_Messenger_Collection_Loader'                                                                              => [
492
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
493
+			],
494
+			'EE_Message_Type_Collection_Loader'                                                                           => [
495
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
496
+			],
497
+			'EE_Message_Resource_Manager'                                                                                 => [
498
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
499
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
500
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
501
+			],
502
+			'EE_Message_Factory'                                                                                          => [
503
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
504
+			],
505
+			'EE_messages'                                                                                                 => [
506
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
507
+			],
508
+			'EE_Messages_Generator'                                                                                       => [
509
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
510
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
511
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
512
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
513
+			],
514
+			'EE_Messages_Processor'                                                                                       => [
515
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
516
+			],
517
+			'EE_Messages_Queue'                                                                                           => [
518
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
519
+			],
520
+			'EE_Messages_Template_Defaults'                                                                               => [
521
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
522
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
523
+			],
524
+			'EE_Message_To_Generate_From_Request'                                                                         => [
525
+				'EE_Message_Resource_Manager'                 => EE_Dependency_Map::load_from_cache,
526
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
527
+			],
528
+			'EventEspresso\core\services\commands\CommandBus'                                                             => [
529
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
530
+			],
531
+			'EventEspresso\services\commands\CommandHandler'                                                              => [
532
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
533
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
534
+			],
535
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => [
536
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
537
+			],
538
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => [
539
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
540
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
541
+			],
542
+			'EventEspresso\core\services\commands\CommandFactory'                                                         => [
543
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
544
+			],
545
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => [
546
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
547
+			],
548
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => [
549
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
550
+			],
551
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => [
552
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
553
+			],
554
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => [
555
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
556
+			],
557
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
558
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
559
+			],
560
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
561
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
562
+			],
563
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
564
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
565
+			],
566
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
567
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
568
+			],
569
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
570
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
571
+			],
572
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
573
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
574
+			],
575
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => [
576
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
577
+			],
578
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
579
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
580
+			],
581
+			'EventEspresso\core\services\database\TableManager'                                                           => [
582
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
583
+			],
584
+			'EE_Data_Migration_Class_Base'                                                                                => [
585
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
586
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
587
+			],
588
+			'EE_DMS_Core_4_1_0'                                                                                           => [
589
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
590
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
591
+			],
592
+			'EE_DMS_Core_4_2_0'                                                                                           => [
593
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
594
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
595
+			],
596
+			'EE_DMS_Core_4_3_0'                                                                                           => [
597
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
598
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
599
+			],
600
+			'EE_DMS_Core_4_4_0'                                                                                           => [
601
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
602
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
603
+			],
604
+			'EE_DMS_Core_4_5_0'                                                                                           => [
605
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
606
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
607
+			],
608
+			'EE_DMS_Core_4_6_0'                                                                                           => [
609
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
610
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
611
+			],
612
+			'EE_DMS_Core_4_7_0'                                                                                           => [
613
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
614
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
615
+			],
616
+			'EE_DMS_Core_4_8_0'                                                                                           => [
617
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
618
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
619
+			],
620
+			'EE_DMS_Core_4_9_0'                                                                                           => [
621
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
622
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
623
+			],
624
+			'EE_DMS_Core_4_10_0'                                                                                          => [
625
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
626
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
627
+				'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
628
+			],
629
+			'EE_DMS_Core_4_11_0'                                                                                          => [
630
+				'EE_DMS_Core_4_10_0'                                 => EE_Dependency_Map::load_from_cache,
631
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
632
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
633
+			],
634
+			'EE_DMS_Core_4_12_0'                                                                                          => [
635
+				'EE_DMS_Core_4_11_0'                                 => EE_Dependency_Map::load_from_cache,
636
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
637
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
638
+			],
639
+			'EventEspresso\core\services\assets\I18nRegistry'                                                             => [
640
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
641
+			],
642
+			'EventEspresso\core\services\assets\Registry'                                                                 => [
643
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
644
+				'EventEspresso\core\services\assets\AssetManifest'   => EE_Dependency_Map::load_from_cache,
645
+			],
646
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCancelled'                                             => [
647
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
648
+			],
649
+			'EventEspresso\core\domain\entities\shortcodes\EspressoCheckout'                                              => [
650
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
651
+			],
652
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEventAttendees'                                        => [
653
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
654
+			],
655
+			'EventEspresso\core\domain\entities\shortcodes\EspressoEvents'                                                => [
656
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
657
+			],
658
+			'EventEspresso\core\domain\entities\shortcodes\EspressoThankYou'                                              => [
659
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
660
+			],
661
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTicketSelector'                                        => [
662
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
663
+			],
664
+			'EventEspresso\core\domain\entities\shortcodes\EspressoTxnPage'                                               => [
665
+				'EventEspresso\core\services\cache\PostRelatedCacheManager' => EE_Dependency_Map::load_from_cache,
666
+			],
667
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => [
668
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
669
+			],
670
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => [
671
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
672
+			],
673
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => [
674
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
675
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
676
+			],
677
+			'EventEspresso\core\domain\values\EmailAddress'                                                               => [
678
+				null,
679
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
680
+			],
681
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => [
682
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
683
+			],
684
+			'LEGACY_MODELS'                                                                                               => [
685
+				null,
686
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
687
+			],
688
+			'EE_Module_Request_Router'                                                                                    => [
689
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
690
+			],
691
+			'EE_Registration_Processor'                                                                                   => [
692
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
693
+			],
694
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => [
695
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
696
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
697
+			],
698
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => [
699
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
700
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
701
+			],
702
+			'EventEspresso\modules\ticket_selector\DisplayTicketSelector'                                                 => [
703
+				'EventEspresso\core\domain\entities\users\CurrentUser' => EE_Dependency_Map::load_from_cache,
704
+				'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
705
+				'EE_Ticket_Selector_Config'                            => EE_Dependency_Map::load_from_cache,
706
+			],
707
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => [
708
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
709
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
710
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
711
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
712
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
713
+			],
714
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => [
715
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
716
+			],
717
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => [
718
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
719
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
720
+			],
721
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => [
722
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
723
+			],
724
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => [
725
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
726
+			],
727
+			'EE_CPT_Strategy'                                                                                             => [
728
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
729
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
730
+			],
731
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => [
732
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
733
+			],
734
+			'EventEspresso\core\CPTs\CptQueryModifier'                                                                    => [
735
+				null,
736
+				null,
737
+				null,
738
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
739
+				'EventEspresso\core\services\request\Request'     => EE_Dependency_Map::load_from_cache,
740
+				'EventEspresso\core\services\loaders\Loader'      => EE_Dependency_Map::load_from_cache,
741
+			],
742
+			'EventEspresso\core\services\dependencies\DependencyResolver'                                                 => [
743
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
744
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
745
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
746
+			],
747
+			'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                               => [
748
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
749
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
750
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
751
+			],
752
+			'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                          => [
753
+				'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
754
+				'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
755
+			],
756
+			'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                          => [
757
+				'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
758
+				'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
759
+			],
760
+			'EE_URL_Validation_Strategy'                                                                                  => [
761
+				null,
762
+				null,
763
+				'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache,
764
+			],
765
+			'EventEspresso\core\services\request\files\FilesDataHandler'                                                  => [
766
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
767
+			],
768
+			'EventEspressoBatchRequest\BatchRequestProcessor'                                                             => [
769
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
770
+			],
771
+			'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                => [
772
+				'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
773
+				'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
774
+				'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
775
+				null,
776
+			],
777
+			'EventEspresso\core\services\routing\RouteHandler'                                                            => [
778
+				'EventEspresso\core\services\json\JsonDataNodeHandler' => EE_Dependency_Map::load_from_cache,
779
+				'EventEspresso\core\services\loaders\Loader'           => EE_Dependency_Map::load_from_cache,
780
+				'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
781
+				'EventEspresso\core\services\routing\RouteCollection'  => EE_Dependency_Map::load_from_cache,
782
+			],
783
+			'EventEspresso\core\services\json\JsonDataNodeHandler'                                                        => [
784
+				'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
785
+			],
786
+			'EventEspresso\core\services\routing\Router'                                                                  => [
787
+				'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
788
+				'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
789
+				'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
790
+			],
791
+			'EventEspresso\core\services\assets\AssetManifest'                                                            => [
792
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
793
+			],
794
+			'EventEspresso\core\services\assets\AssetManifestFactory'                                                     => [
795
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
796
+			],
797
+			'EventEspresso\core\services\assets\BaristaFactory'                                                           => [
798
+				'EventEspresso\core\services\assets\AssetManifestFactory' => EE_Dependency_Map::load_from_cache,
799
+				'EventEspresso\core\services\loaders\Loader'              => EE_Dependency_Map::load_from_cache,
800
+			],
801
+			'EventEspresso\core\domain\services\capabilities\FeatureFlags'                                                => [
802
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
803
+				'EventEspresso\core\domain\Domain' => EE_Dependency_Map::load_from_cache,
804
+			],
805
+			'EventEspresso\core\services\addon\AddonManager'                                                              => [
806
+				'EventEspresso\core\services\addon\AddonCollection'              => EE_Dependency_Map::load_from_cache,
807
+				'EventEspresso\core\Psr4Autoloader'                              => EE_Dependency_Map::load_from_cache,
808
+				'EventEspresso\core\services\addon\api\v1\RegisterAddon'         => EE_Dependency_Map::load_from_cache,
809
+				'EventEspresso\core\services\addon\api\IncompatibleAddonHandler' => EE_Dependency_Map::load_from_cache,
810
+				'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'  => EE_Dependency_Map::load_from_cache,
811
+			],
812
+			'EventEspresso\core\services\addon\api\ThirdPartyPluginHandler'                                               => [
813
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
814
+			],
815
+			'EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion'                                                  => [
816
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
817
+			],
818
+			'EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'                                                  => [
819
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
820
+			],
821
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'                                        => [
822
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
823
+				'EEM_Event'                                                   => EE_Dependency_Map::load_from_cache,
824
+				'EEM_Datetime'                                                => EE_Dependency_Map::load_from_cache,
825
+				'EEM_Registration'                                            => EE_Dependency_Map::load_from_cache,
826
+			],
827
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'                                        => [
828
+				'EventEspresso\core\services\orm\tree_traversal\NodeGroupDao' => EE_Dependency_Map::load_from_cache,
829
+			],
830
+			'EventEspresso\core\services\request\CurrentPage'                                                             => [
831
+				'EE_CPT_Strategy'                             => EE_Dependency_Map::load_from_cache,
832
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
833
+			],
834
+			'EventEspresso\core\services\shortcodes\LegacyShortcodesManager'                                              => [
835
+				'EE_Registry'                                     => EE_Dependency_Map::load_from_cache,
836
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
837
+			],
838
+			'EventEspresso\core\services\shortcodes\ShortcodesManager'                                                    => [
839
+				'EventEspresso\core\services\shortcodes\LegacyShortcodesManager' => EE_Dependency_Map::load_from_cache,
840
+				'EventEspresso\core\services\request\CurrentPage'                => EE_Dependency_Map::load_from_cache,
841
+			],
842
+			'EventEspresso\core\domain\entities\users\CurrentUser'                                                        => [
843
+				'EventEspresso\core\domain\entities\users\EventManagers' => EE_Dependency_Map::load_from_cache,
844
+			],
845
+			'EventEspresso\core\services\form\meta\InputTypes'                                                            => [
846
+				'EventEspresso\core\services\form\meta\inputs\Block'    => EE_Dependency_Map::load_from_cache,
847
+				'EventEspresso\core\services\form\meta\inputs\Button'   => EE_Dependency_Map::load_from_cache,
848
+				'EventEspresso\core\services\form\meta\inputs\DateTime' => EE_Dependency_Map::load_from_cache,
849
+				'EventEspresso\core\services\form\meta\inputs\Input'    => EE_Dependency_Map::load_from_cache,
850
+				'EventEspresso\core\services\form\meta\inputs\Number'   => EE_Dependency_Map::load_from_cache,
851
+				'EventEspresso\core\services\form\meta\inputs\Phone'    => EE_Dependency_Map::load_from_cache,
852
+				'EventEspresso\core\services\form\meta\inputs\Select'   => EE_Dependency_Map::load_from_cache,
853
+				'EventEspresso\core\services\form\meta\inputs\Text'     => EE_Dependency_Map::load_from_cache,
854
+			],
855
+			'EventEspresso\core\domain\services\registration\form\v1\RegFormDependencyHandler'                            => [
856
+				'EE_Dependency_Map' => EE_Dependency_Map::load_from_cache,
857
+			],
858
+			'EventEspresso\core\services\calculators\LineItemCalculator'                                                  => [
859
+				'EventEspresso\core\services\helpers\DecimalValues' => EE_Dependency_Map::load_from_cache,
860
+			],
861
+			'EventEspresso\core\services\helpers\DecimalValues'                                                           => [
862
+				'EE_Currency_Config' => EE_Dependency_Map::load_from_cache,
863
+			],
864
+		];
865
+	}
866
+
867
+
868
+	/**
869
+	 * Registers how core classes are loaded.
870
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
871
+	 *        'EE_Request_Handler' => 'load_core'
872
+	 *        'EE_Messages_Queue'  => 'load_lib'
873
+	 *        'EEH_Debug_Tools'    => 'load_helper'
874
+	 * or, if greater control is required, by providing a custom closure. For example:
875
+	 *        'Some_Class' => function () {
876
+	 *            return new Some_Class();
877
+	 *        },
878
+	 * This is required for instantiating dependencies
879
+	 * where an interface has been type hinted in a class constructor. For example:
880
+	 *        'Required_Interface' => function () {
881
+	 *            return new A_Class_That_Implements_Required_Interface();
882
+	 *        },
883
+	 */
884
+	protected function _register_core_class_loaders()
885
+	{
886
+		$this->_class_loaders = [
887
+			// load_core
888
+			'EE_Dependency_Map'                            => function () {
889
+				return $this;
890
+			},
891
+			'EE_Capabilities'                              => 'load_core',
892
+			'EE_Encryption'                                => 'load_core',
893
+			'EE_Front_Controller'                          => 'load_core',
894
+			'EE_Module_Request_Router'                     => 'load_core',
895
+			'EE_Registry'                                  => 'load_core',
896
+			'EE_Request'                                   => function () {
897
+				return $this->legacy_request;
898
+			},
899
+			'EventEspresso\core\services\request\Request'  => function () {
900
+				return $this->request;
901
+			},
902
+			'EventEspresso\core\services\request\Response' => function () {
903
+				return $this->response;
904
+			},
905
+			'EE_Base'                                      => 'load_core',
906
+			'EE_Request_Handler'                           => 'load_core',
907
+			'EE_Session'                                   => 'load_core',
908
+			'EE_Cron_Tasks'                                => 'load_core',
909
+			'EE_System'                                    => 'load_core',
910
+			'EE_Maintenance_Mode'                          => 'load_core',
911
+			'EE_Register_CPTs'                             => 'load_core',
912
+			'EE_Admin'                                     => 'load_core',
913
+			'EE_CPT_Strategy'                              => 'load_core',
914
+			// load_class
915
+			'EE_Registration_Processor'                    => 'load_class',
916
+			// load_lib
917
+			'EE_Message_Resource_Manager'                  => 'load_lib',
918
+			'EE_Message_Type_Collection'                   => 'load_lib',
919
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
920
+			'EE_Messenger_Collection'                      => 'load_lib',
921
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
922
+			'EE_Messages_Processor'                        => 'load_lib',
923
+			'EE_Message_Repository'                        => 'load_lib',
924
+			'EE_Messages_Queue'                            => 'load_lib',
925
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
926
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
927
+			'EE_Payment_Method_Manager'                    => 'load_lib',
928
+			'EE_DMS_Core_4_1_0'                            => 'load_dms',
929
+			'EE_DMS_Core_4_2_0'                            => 'load_dms',
930
+			'EE_DMS_Core_4_3_0'                            => 'load_dms',
931
+			'EE_DMS_Core_4_5_0'                            => 'load_dms',
932
+			'EE_DMS_Core_4_6_0'                            => 'load_dms',
933
+			'EE_DMS_Core_4_7_0'                            => 'load_dms',
934
+			'EE_DMS_Core_4_8_0'                            => 'load_dms',
935
+			'EE_DMS_Core_4_9_0'                            => 'load_dms',
936
+			'EE_DMS_Core_4_10_0'                           => 'load_dms',
937
+			'EE_DMS_Core_4_11_0'                           => 'load_dms',
938
+			'EE_DMS_Core_4_12_0'                           => 'load_dms',
939
+			'EE_Messages_Generator'                        => static function () {
940
+				return EE_Registry::instance()->load_lib(
941
+					'Messages_Generator',
942
+					[],
943
+					false,
944
+					false
945
+				);
946
+			},
947
+			'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
948
+				return EE_Registry::instance()->load_lib(
949
+					'Messages_Template_Defaults',
950
+					$arguments,
951
+					false,
952
+					false
953
+				);
954
+			},
955
+			// load_helper
956
+			'EEH_Parse_Shortcodes'                         => static function () {
957
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
958
+					return new EEH_Parse_Shortcodes();
959
+				}
960
+				return null;
961
+			},
962
+			'EE_Template_Config'                           => static function () {
963
+				return EE_Config::instance()->template_settings;
964
+			},
965
+			'EE_Currency_Config'                           => static function () {
966
+				return EE_Currency_Config::getCurrencyConfig();
967
+			},
968
+			'EE_Registration_Config'                       => static function () {
969
+				return EE_Config::instance()->registration;
970
+			},
971
+			'EE_Core_Config'                               => static function () {
972
+				return EE_Config::instance()->core;
973
+			},
974
+			'EventEspresso\core\services\loaders\Loader'   => static function () {
975
+				return LoaderFactory::getLoader();
976
+			},
977
+			'EE_Network_Config'                            => static function () {
978
+				return EE_Network_Config::instance();
979
+			},
980
+			'EE_Config'                                    => static function () {
981
+				return EE_Config::instance();
982
+			},
983
+			'EventEspresso\core\domain\Domain'             => static function () {
984
+				return DomainFactory::getEventEspressoCoreDomain();
985
+			},
986
+			'EE_Admin_Config'                              => static function () {
987
+				return EE_Config::instance()->admin;
988
+			},
989
+			'EE_Organization_Config'                       => static function () {
990
+				return EE_Config::instance()->organization;
991
+			},
992
+			'EE_Network_Core_Config'                       => static function () {
993
+				return EE_Network_Config::instance()->core;
994
+			},
995
+			'EE_Environment_Config'                        => static function () {
996
+				return EE_Config::instance()->environment;
997
+			},
998
+			'EED_Core_Rest_Api'                            => static function () {
999
+				return EED_Core_Rest_Api::instance();
1000
+			},
1001
+			'WP_REST_Server'                               => static function () {
1002
+				return rest_get_server();
1003
+			},
1004
+			'EventEspresso\core\Psr4Autoloader'            => static function () {
1005
+				return EE_Psr4AutoloaderInit::psr4_loader();
1006
+			},
1007
+			'EE_Ticket_Selector_Config'                    => function () {
1008
+				return EE_Config::instance()->template_settings->EED_Ticket_Selector;
1009
+			},
1010
+		];
1011
+	}
1012
+
1013
+
1014
+	/**
1015
+	 * can be used for supplying alternate names for classes,
1016
+	 * or for connecting interface names to instantiable classes
1017
+	 *
1018
+	 * @throws InvalidAliasException
1019
+	 */
1020
+	protected function _register_core_aliases()
1021
+	{
1022
+		$aliases = [
1023
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
1024
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
1025
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
1026
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
1027
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
1028
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
1029
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1030
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
1031
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
1032
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
1033
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1034
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
1035
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
1036
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
1037
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
1038
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
1039
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
1040
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
1041
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
1042
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
1043
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1044
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
1045
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
1046
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
1047
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
1048
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
1049
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
1050
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
1051
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
1052
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
1053
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
1054
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
1055
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
1056
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
1057
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
1058
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
1059
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
1060
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
1061
+			'EventEspresso\core\services\assets\AssetManifestInterface'                    => 'EventEspresso\core\services\assets\AssetManifest',
1062
+		];
1063
+		foreach ($aliases as $alias => $fqn) {
1064
+			if (is_array($fqn)) {
1065
+				foreach ($fqn as $class => $for_class) {
1066
+					$this->class_cache->addAlias($class, $alias, $for_class);
1067
+				}
1068
+				continue;
1069
+			}
1070
+			$this->class_cache->addAlias($fqn, $alias);
1071
+		}
1072
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1073
+			$this->class_cache->addAlias(
1074
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
1075
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
1076
+			);
1077
+		}
1078
+	}
1079
+
1080
+
1081
+	public function debug($for_class = '')
1082
+	{
1083
+		if (method_exists($this->class_cache, 'debug')) {
1084
+			$this->class_cache->debug($for_class);
1085
+		}
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
1091
+	 * request Primarily used by unit tests.
1092
+	 */
1093
+	public function reset()
1094
+	{
1095
+		$this->_register_core_class_loaders();
1096
+		$this->_register_core_dependencies();
1097
+	}
1098
+
1099
+
1100
+	/**
1101
+	 * PLZ NOTE: a better name for this method would be is_alias()
1102
+	 * because it returns TRUE if the provided fully qualified name IS an alias
1103
+	 * WHY?
1104
+	 * Because if a class is type hinting for a concretion,
1105
+	 * then why would we need to find another class to supply it?
1106
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
1107
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
1108
+	 * Don't go looking for some substitute.
1109
+	 * Whereas if a class is type hinting for an interface...
1110
+	 * then we need to find an actual class to use.
1111
+	 * So the interface IS the alias for some other FQN,
1112
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
1113
+	 * represents some other class.
1114
+	 *
1115
+	 * @param string $fqn
1116
+	 * @param string $for_class
1117
+	 * @return bool
1118
+	 * @deprecated 4.9.62.p
1119
+	 */
1120
+	public function has_alias(string $fqn = '', string $for_class = ''): bool
1121
+	{
1122
+		return $this->isAlias($fqn, $for_class);
1123
+	}
1124
+
1125
+
1126
+	/**
1127
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
1128
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
1129
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
1130
+	 *  for example:
1131
+	 *      if the following two entries were added to the _aliases array:
1132
+	 *          array(
1133
+	 *              'interface_alias'           => 'some\namespace\interface'
1134
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1135
+	 *          )
1136
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1137
+	 *      to load an instance of 'some\namespace\classname'
1138
+	 *
1139
+	 * @param string $alias
1140
+	 * @param string $for_class
1141
+	 * @return string
1142
+	 * @deprecated 4.9.62.p
1143
+	 */
1144
+	public function get_alias(string $alias = '', string $for_class = ''): string
1145
+	{
1146
+		return $this->getFqnForAlias($alias, $for_class);
1147
+	}
1148 1148
 }
Please login to merge, or discard this patch.
core/admin/EE_Admin_List_Table.core.php 2 patches
Indentation   +920 added lines, -920 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
4 4
 
5 5
 if (! class_exists('WP_List_Table')) {
6
-    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
6
+	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
7 7
 }
8 8
 
9 9
 
@@ -21,925 +21,925 @@  discard block
 block discarded – undo
21 21
  */
22 22
 abstract class EE_Admin_List_Table extends WP_List_Table
23 23
 {
24
-    const ACTION_COPY    = 'duplicate';
25
-
26
-    const ACTION_DELETE  = 'delete';
27
-
28
-    const ACTION_EDIT    = 'edit';
29
-
30
-    const ACTION_RESTORE = 'restore';
31
-
32
-    const ACTION_TRASH   = 'trash';
33
-
34
-    protected static $actions = [
35
-        self::ACTION_COPY,
36
-        self::ACTION_DELETE,
37
-        self::ACTION_EDIT,
38
-        self::ACTION_RESTORE,
39
-        self::ACTION_TRASH,
40
-    ];
41
-
42
-    /**
43
-     * holds the data that will be processed for the table
44
-     *
45
-     * @var array $_data
46
-     */
47
-    protected $_data;
48
-
49
-
50
-    /**
51
-     * This holds the value of all the data available for the given view (for all pages).
52
-     *
53
-     * @var int $_all_data_count
54
-     */
55
-    protected $_all_data_count;
56
-
57
-
58
-    /**
59
-     * Will contain the count of trashed items for the view label.
60
-     *
61
-     * @var int $_trashed_count
62
-     */
63
-    protected $_trashed_count;
64
-
65
-
66
-    /**
67
-     * This is what will be referenced as the slug for the current screen
68
-     *
69
-     * @var string $_screen
70
-     */
71
-    protected $_screen;
72
-
73
-
74
-    /**
75
-     * this is the EE_Admin_Page object
76
-     *
77
-     * @var EE_Admin_Page $_admin_page
78
-     */
79
-    protected $_admin_page;
80
-
81
-
82
-    /**
83
-     * The current view
84
-     *
85
-     * @var string $_view
86
-     */
87
-    protected $_view;
88
-
89
-
90
-    /**
91
-     * array of possible views for this table
92
-     *
93
-     * @var array $_views
94
-     */
95
-    protected $_views;
96
-
97
-
98
-    /**
99
-     * An array of key => value pairs containing information about the current table
100
-     * array(
101
-     *        'plural' => 'plural label',
102
-     *        'singular' => 'singular label',
103
-     *        'ajax' => false, //whether to use ajax or not
104
-     *        'screen' => null, //string used to reference what screen this is
105
-     *        (WP_List_table converts to screen object)
106
-     * )
107
-     *
108
-     * @var array $_wp_list_args
109
-     */
110
-    protected $_wp_list_args;
111
-
112
-    /**
113
-     * an array of column names
114
-     * array(
115
-     *    'internal-name' => 'Title'
116
-     * )
117
-     *
118
-     * @var array $_columns
119
-     */
120
-    protected $_columns;
121
-
122
-    /**
123
-     * An array of sortable columns
124
-     * array(
125
-     *    'internal-name' => 'orderby' //or
126
-     *    'internal-name' => array( 'orderby', true )
127
-     * )
128
-     *
129
-     * @var array $_sortable_columns
130
-     */
131
-    protected $_sortable_columns;
132
-
133
-    /**
134
-     * callback method used to perform AJAX row reordering
135
-     *
136
-     * @var string $_ajax_sorting_callback
137
-     */
138
-    protected $_ajax_sorting_callback;
139
-
140
-    /**
141
-     * An array of hidden columns (if needed)
142
-     * array('internal-name', 'internal-name')
143
-     *
144
-     * @var array $_hidden_columns
145
-     */
146
-    protected $_hidden_columns;
147
-
148
-    /**
149
-     * holds the per_page value
150
-     *
151
-     * @var int $_per_page
152
-     */
153
-    protected $_per_page;
154
-
155
-    /**
156
-     * holds what page number is currently being viewed
157
-     *
158
-     * @var int $_current_page
159
-     */
160
-    protected $_current_page;
161
-
162
-    /**
163
-     * the reference string for the nonce_action
164
-     *
165
-     * @var string $_nonce_action_ref
166
-     */
167
-    protected $_nonce_action_ref;
168
-
169
-    /**
170
-     * property to hold incoming request data (as set by the admin_page_core)
171
-     *
172
-     * @var array $_req_data
173
-     */
174
-    protected $_req_data;
175
-
176
-
177
-    /**
178
-     * yes / no array for admin form fields
179
-     *
180
-     * @var array $_yes_no
181
-     */
182
-    protected $_yes_no = [];
183
-
184
-    /**
185
-     * Array describing buttons that should appear at the bottom of the page
186
-     * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
187
-     * and the values are another array with the following keys
188
-     * array(
189
-     *    'route' => 'page_route',
190
-     *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
191
-     * )
192
-     *
193
-     * @var array $_bottom_buttons
194
-     */
195
-    protected $_bottom_buttons = [];
196
-
197
-
198
-    /**
199
-     * Used to indicate what should be the primary column for the list table.
200
-     * If not present then falls back to what WP calculates
201
-     * as the primary column.
202
-     *
203
-     * @type string $_primary_column
204
-     */
205
-    protected $_primary_column = '';
206
-
207
-
208
-    /**
209
-     * Used to indicate whether the table has a checkbox column or not.
210
-     *
211
-     * @type bool $_has_checkbox_column
212
-     */
213
-    protected $_has_checkbox_column = false;
214
-
215
-
216
-    /**
217
-     * @param EE_Admin_Page $admin_page we use this for obtaining everything we need in the list table
218
-     */
219
-    public function __construct(EE_Admin_Page $admin_page)
220
-    {
221
-        $this->_admin_page   = $admin_page;
222
-        $this->_req_data     = $this->_admin_page->get_request_data();
223
-        $this->_view         = $this->_admin_page->get_view();
224
-        $this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
225
-        $this->_current_page = $this->get_pagenum();
226
-        $this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
227
-        $this->_yes_no       = [
228
-            esc_html__('No', 'event_espresso'),
229
-            esc_html__('Yes', 'event_espresso')
230
-        ];
231
-
232
-        $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
233
-
234
-        $this->_setup_data();
235
-        $this->_add_view_counts();
236
-
237
-        $this->_nonce_action_ref = $this->_view;
238
-
239
-        $this->_set_properties();
240
-
241
-        // set primary column
242
-        add_filter('list_table_primary_column', [$this, 'set_primary_column']);
243
-
244
-        // set parent defaults
245
-        parent::__construct($this->_wp_list_args);
246
-
247
-        $this->prepare_items();
248
-    }
249
-
250
-
251
-    /**
252
-     * _setup_data
253
-     * this method is used to setup the $_data, $_all_data_count, and _per_page properties
254
-     *
255
-     * @return void
256
-     * @uses $this->_admin_page
257
-     */
258
-    abstract protected function _setup_data();
259
-
260
-
261
-    /**
262
-     * set the properties that this class needs to be able to execute wp_list_table properly
263
-     * properties set:
264
-     * _wp_list_args = what the arguments required for the parent _wp_list_table.
265
-     * _columns = set the columns in an array.
266
-     * _sortable_columns = columns that are sortable (array).
267
-     * _hidden_columns = columns that are hidden (array)
268
-     * _default_orderby = the default orderby for sorting.
269
-     *
270
-     * @abstract
271
-     * @access protected
272
-     * @return void
273
-     */
274
-    abstract protected function _set_properties();
275
-
276
-
277
-    /**
278
-     * _get_table_filters
279
-     * We use this to assemble and return any filters that are associated with this table that help further refine what
280
-     * gets shown in the table.
281
-     *
282
-     * @abstract
283
-     * @access protected
284
-     * @return string
285
-     */
286
-    abstract protected function _get_table_filters();
287
-
288
-
289
-    /**
290
-     * this is a method that child class will do to add counts to the views array so when views are displayed the
291
-     * counts of the views is accurate.
292
-     *
293
-     * @abstract
294
-     * @access protected
295
-     * @return void
296
-     */
297
-    abstract protected function _add_view_counts();
298
-
299
-
300
-    /**
301
-     * _get_hidden_fields
302
-     * returns a html string of hidden fields so if any table filters are used the current view will be respected.
303
-     *
304
-     * @return string
305
-     */
306
-    protected function _get_hidden_fields()
307
-    {
308
-        $action = isset($this->_req_data['route']) ? $this->_req_data['route'] : '';
309
-        $action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
310
-        // if action is STILL empty, then we set it to default
311
-        $action = empty($action) ? 'default' : $action;
312
-        $field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
313
-        $field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
314
-        $field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
315
-
316
-        $bulk_actions = $this->_get_bulk_actions();
317
-        foreach ($bulk_actions as $bulk_action => $label) {
318
-            $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
319
-                      . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
320
-        }
321
-
322
-        return $field;
323
-    }
324
-
325
-
326
-    /**
327
-     * _set_column_info
328
-     * we're using this to set the column headers property.
329
-     *
330
-     * @access protected
331
-     * @return void
332
-     */
333
-    protected function _set_column_info()
334
-    {
335
-        $columns   = $this->get_columns();
336
-        $hidden    = $this->get_hidden_columns();
337
-        $_sortable = $this->get_sortable_columns();
338
-
339
-        /**
340
-         * Dynamic hook allowing for adding sortable columns in this list table.
341
-         * Note that $this->screen->id is in the format
342
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
343
-         * table it is: event-espresso_page_espresso_messages.
344
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
345
-         * hook prefix ("event-espresso") will be different.
346
-         *
347
-         * @var array
348
-         */
349
-        $_sortable = apply_filters("FHEE_manage_{$this->screen->id}_sortable_columns", $_sortable, $this->_screen);
350
-
351
-        $sortable = [];
352
-        foreach ($_sortable as $id => $data) {
353
-            if (empty($data)) {
354
-                continue;
355
-            }
356
-            // fix for offset errors with WP_List_Table default get_columninfo()
357
-            if (is_array($data)) {
358
-                $_data[0] = key($data);
359
-                $_data[1] = isset($data[1]) ? $data[1] : false;
360
-            } else {
361
-                $_data[0] = $data;
362
-            }
363
-
364
-            $data = (array) $data;
365
-
366
-            if (! isset($data[1])) {
367
-                $_data[1] = false;
368
-            }
369
-
370
-            $sortable[ $id ] = $_data;
371
-        }
372
-        $primary               = $this->get_primary_column_name();
373
-        $this->_column_headers = [$columns, $hidden, $sortable, $primary];
374
-    }
375
-
376
-
377
-    /**
378
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
379
-     *
380
-     * @return string
381
-     */
382
-    protected function get_primary_column_name()
383
-    {
384
-        foreach (class_parents($this) as $parent) {
385
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
386
-                return parent::get_primary_column_name();
387
-            }
388
-        }
389
-        return $this->_primary_column;
390
-    }
391
-
392
-
393
-    /**
394
-     * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
395
-     *
396
-     * @param EE_Base_Class $item
397
-     * @param string        $column_name
398
-     * @param string        $primary
399
-     * @return string
400
-     */
401
-    protected function handle_row_actions($item, $column_name, $primary)
402
-    {
403
-        foreach (class_parents($this) as $parent) {
404
-            if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
405
-                return parent::handle_row_actions($item, $column_name, $primary);
406
-            }
407
-        }
408
-        return '';
409
-    }
410
-
411
-
412
-    /**
413
-     * _get_bulk_actions
414
-     * This is a wrapper called by WP_List_Table::get_bulk_actions()
415
-     *
416
-     * @access protected
417
-     * @return array bulk_actions
418
-     */
419
-    protected function _get_bulk_actions(): array
420
-    {
421
-        $actions = [];
422
-        // the _views property should have the bulk_actions, so let's go through and extract them into a properly
423
-        // formatted array for the wp_list_table();
424
-        foreach ($this->_views as $view => $args) {
425
-            if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
426
-                // each bulk action will correspond with a admin page route, so we can check whatever the capability is
427
-                // for that page route and skip adding the bulk action if no access for the current logged in user.
428
-                foreach ($args['bulk_action'] as $route => $label) {
429
-                    if ($this->_admin_page->check_user_access($route, true)) {
430
-                        $actions[ $route ] = $label;
431
-                    }
432
-                }
433
-            }
434
-        }
435
-        return $actions;
436
-    }
437
-
438
-
439
-    /**
440
-     * Generate the table navigation above or below the table.
441
-     * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
442
-     *
443
-     * @throws EE_Error
444
-     * @since 4.9.44.rc.001
445
-     */
446
-    public function display_tablenav($which)
447
-    {
448
-        if ('top' === $which) {
449
-            wp_nonce_field('bulk-' . $this->_args['plural']);
450
-        }
451
-        ?>
24
+	const ACTION_COPY    = 'duplicate';
25
+
26
+	const ACTION_DELETE  = 'delete';
27
+
28
+	const ACTION_EDIT    = 'edit';
29
+
30
+	const ACTION_RESTORE = 'restore';
31
+
32
+	const ACTION_TRASH   = 'trash';
33
+
34
+	protected static $actions = [
35
+		self::ACTION_COPY,
36
+		self::ACTION_DELETE,
37
+		self::ACTION_EDIT,
38
+		self::ACTION_RESTORE,
39
+		self::ACTION_TRASH,
40
+	];
41
+
42
+	/**
43
+	 * holds the data that will be processed for the table
44
+	 *
45
+	 * @var array $_data
46
+	 */
47
+	protected $_data;
48
+
49
+
50
+	/**
51
+	 * This holds the value of all the data available for the given view (for all pages).
52
+	 *
53
+	 * @var int $_all_data_count
54
+	 */
55
+	protected $_all_data_count;
56
+
57
+
58
+	/**
59
+	 * Will contain the count of trashed items for the view label.
60
+	 *
61
+	 * @var int $_trashed_count
62
+	 */
63
+	protected $_trashed_count;
64
+
65
+
66
+	/**
67
+	 * This is what will be referenced as the slug for the current screen
68
+	 *
69
+	 * @var string $_screen
70
+	 */
71
+	protected $_screen;
72
+
73
+
74
+	/**
75
+	 * this is the EE_Admin_Page object
76
+	 *
77
+	 * @var EE_Admin_Page $_admin_page
78
+	 */
79
+	protected $_admin_page;
80
+
81
+
82
+	/**
83
+	 * The current view
84
+	 *
85
+	 * @var string $_view
86
+	 */
87
+	protected $_view;
88
+
89
+
90
+	/**
91
+	 * array of possible views for this table
92
+	 *
93
+	 * @var array $_views
94
+	 */
95
+	protected $_views;
96
+
97
+
98
+	/**
99
+	 * An array of key => value pairs containing information about the current table
100
+	 * array(
101
+	 *        'plural' => 'plural label',
102
+	 *        'singular' => 'singular label',
103
+	 *        'ajax' => false, //whether to use ajax or not
104
+	 *        'screen' => null, //string used to reference what screen this is
105
+	 *        (WP_List_table converts to screen object)
106
+	 * )
107
+	 *
108
+	 * @var array $_wp_list_args
109
+	 */
110
+	protected $_wp_list_args;
111
+
112
+	/**
113
+	 * an array of column names
114
+	 * array(
115
+	 *    'internal-name' => 'Title'
116
+	 * )
117
+	 *
118
+	 * @var array $_columns
119
+	 */
120
+	protected $_columns;
121
+
122
+	/**
123
+	 * An array of sortable columns
124
+	 * array(
125
+	 *    'internal-name' => 'orderby' //or
126
+	 *    'internal-name' => array( 'orderby', true )
127
+	 * )
128
+	 *
129
+	 * @var array $_sortable_columns
130
+	 */
131
+	protected $_sortable_columns;
132
+
133
+	/**
134
+	 * callback method used to perform AJAX row reordering
135
+	 *
136
+	 * @var string $_ajax_sorting_callback
137
+	 */
138
+	protected $_ajax_sorting_callback;
139
+
140
+	/**
141
+	 * An array of hidden columns (if needed)
142
+	 * array('internal-name', 'internal-name')
143
+	 *
144
+	 * @var array $_hidden_columns
145
+	 */
146
+	protected $_hidden_columns;
147
+
148
+	/**
149
+	 * holds the per_page value
150
+	 *
151
+	 * @var int $_per_page
152
+	 */
153
+	protected $_per_page;
154
+
155
+	/**
156
+	 * holds what page number is currently being viewed
157
+	 *
158
+	 * @var int $_current_page
159
+	 */
160
+	protected $_current_page;
161
+
162
+	/**
163
+	 * the reference string for the nonce_action
164
+	 *
165
+	 * @var string $_nonce_action_ref
166
+	 */
167
+	protected $_nonce_action_ref;
168
+
169
+	/**
170
+	 * property to hold incoming request data (as set by the admin_page_core)
171
+	 *
172
+	 * @var array $_req_data
173
+	 */
174
+	protected $_req_data;
175
+
176
+
177
+	/**
178
+	 * yes / no array for admin form fields
179
+	 *
180
+	 * @var array $_yes_no
181
+	 */
182
+	protected $_yes_no = [];
183
+
184
+	/**
185
+	 * Array describing buttons that should appear at the bottom of the page
186
+	 * Keys are strings that represent the button's function (specifically a key in _labels['buttons']),
187
+	 * and the values are another array with the following keys
188
+	 * array(
189
+	 *    'route' => 'page_route',
190
+	 *    'extra_request' => array('evt_id' => 1 ); //extra request vars that need to be included in the button.
191
+	 * )
192
+	 *
193
+	 * @var array $_bottom_buttons
194
+	 */
195
+	protected $_bottom_buttons = [];
196
+
197
+
198
+	/**
199
+	 * Used to indicate what should be the primary column for the list table.
200
+	 * If not present then falls back to what WP calculates
201
+	 * as the primary column.
202
+	 *
203
+	 * @type string $_primary_column
204
+	 */
205
+	protected $_primary_column = '';
206
+
207
+
208
+	/**
209
+	 * Used to indicate whether the table has a checkbox column or not.
210
+	 *
211
+	 * @type bool $_has_checkbox_column
212
+	 */
213
+	protected $_has_checkbox_column = false;
214
+
215
+
216
+	/**
217
+	 * @param EE_Admin_Page $admin_page we use this for obtaining everything we need in the list table
218
+	 */
219
+	public function __construct(EE_Admin_Page $admin_page)
220
+	{
221
+		$this->_admin_page   = $admin_page;
222
+		$this->_req_data     = $this->_admin_page->get_request_data();
223
+		$this->_view         = $this->_admin_page->get_view();
224
+		$this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
225
+		$this->_current_page = $this->get_pagenum();
226
+		$this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
227
+		$this->_yes_no       = [
228
+			esc_html__('No', 'event_espresso'),
229
+			esc_html__('Yes', 'event_espresso')
230
+		];
231
+
232
+		$this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
233
+
234
+		$this->_setup_data();
235
+		$this->_add_view_counts();
236
+
237
+		$this->_nonce_action_ref = $this->_view;
238
+
239
+		$this->_set_properties();
240
+
241
+		// set primary column
242
+		add_filter('list_table_primary_column', [$this, 'set_primary_column']);
243
+
244
+		// set parent defaults
245
+		parent::__construct($this->_wp_list_args);
246
+
247
+		$this->prepare_items();
248
+	}
249
+
250
+
251
+	/**
252
+	 * _setup_data
253
+	 * this method is used to setup the $_data, $_all_data_count, and _per_page properties
254
+	 *
255
+	 * @return void
256
+	 * @uses $this->_admin_page
257
+	 */
258
+	abstract protected function _setup_data();
259
+
260
+
261
+	/**
262
+	 * set the properties that this class needs to be able to execute wp_list_table properly
263
+	 * properties set:
264
+	 * _wp_list_args = what the arguments required for the parent _wp_list_table.
265
+	 * _columns = set the columns in an array.
266
+	 * _sortable_columns = columns that are sortable (array).
267
+	 * _hidden_columns = columns that are hidden (array)
268
+	 * _default_orderby = the default orderby for sorting.
269
+	 *
270
+	 * @abstract
271
+	 * @access protected
272
+	 * @return void
273
+	 */
274
+	abstract protected function _set_properties();
275
+
276
+
277
+	/**
278
+	 * _get_table_filters
279
+	 * We use this to assemble and return any filters that are associated with this table that help further refine what
280
+	 * gets shown in the table.
281
+	 *
282
+	 * @abstract
283
+	 * @access protected
284
+	 * @return string
285
+	 */
286
+	abstract protected function _get_table_filters();
287
+
288
+
289
+	/**
290
+	 * this is a method that child class will do to add counts to the views array so when views are displayed the
291
+	 * counts of the views is accurate.
292
+	 *
293
+	 * @abstract
294
+	 * @access protected
295
+	 * @return void
296
+	 */
297
+	abstract protected function _add_view_counts();
298
+
299
+
300
+	/**
301
+	 * _get_hidden_fields
302
+	 * returns a html string of hidden fields so if any table filters are used the current view will be respected.
303
+	 *
304
+	 * @return string
305
+	 */
306
+	protected function _get_hidden_fields()
307
+	{
308
+		$action = isset($this->_req_data['route']) ? $this->_req_data['route'] : '';
309
+		$action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
310
+		// if action is STILL empty, then we set it to default
311
+		$action = empty($action) ? 'default' : $action;
312
+		$field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
313
+		$field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
314
+		$field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
315
+
316
+		$bulk_actions = $this->_get_bulk_actions();
317
+		foreach ($bulk_actions as $bulk_action => $label) {
318
+			$field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
319
+					  . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
320
+		}
321
+
322
+		return $field;
323
+	}
324
+
325
+
326
+	/**
327
+	 * _set_column_info
328
+	 * we're using this to set the column headers property.
329
+	 *
330
+	 * @access protected
331
+	 * @return void
332
+	 */
333
+	protected function _set_column_info()
334
+	{
335
+		$columns   = $this->get_columns();
336
+		$hidden    = $this->get_hidden_columns();
337
+		$_sortable = $this->get_sortable_columns();
338
+
339
+		/**
340
+		 * Dynamic hook allowing for adding sortable columns in this list table.
341
+		 * Note that $this->screen->id is in the format
342
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
343
+		 * table it is: event-espresso_page_espresso_messages.
344
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
345
+		 * hook prefix ("event-espresso") will be different.
346
+		 *
347
+		 * @var array
348
+		 */
349
+		$_sortable = apply_filters("FHEE_manage_{$this->screen->id}_sortable_columns", $_sortable, $this->_screen);
350
+
351
+		$sortable = [];
352
+		foreach ($_sortable as $id => $data) {
353
+			if (empty($data)) {
354
+				continue;
355
+			}
356
+			// fix for offset errors with WP_List_Table default get_columninfo()
357
+			if (is_array($data)) {
358
+				$_data[0] = key($data);
359
+				$_data[1] = isset($data[1]) ? $data[1] : false;
360
+			} else {
361
+				$_data[0] = $data;
362
+			}
363
+
364
+			$data = (array) $data;
365
+
366
+			if (! isset($data[1])) {
367
+				$_data[1] = false;
368
+			}
369
+
370
+			$sortable[ $id ] = $_data;
371
+		}
372
+		$primary               = $this->get_primary_column_name();
373
+		$this->_column_headers = [$columns, $hidden, $sortable, $primary];
374
+	}
375
+
376
+
377
+	/**
378
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
379
+	 *
380
+	 * @return string
381
+	 */
382
+	protected function get_primary_column_name()
383
+	{
384
+		foreach (class_parents($this) as $parent) {
385
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'get_primary_column_name')) {
386
+				return parent::get_primary_column_name();
387
+			}
388
+		}
389
+		return $this->_primary_column;
390
+	}
391
+
392
+
393
+	/**
394
+	 * Added for WP4.1 backward compat (@see https://events.codebasehq.com/projects/event-espresso/tickets/8814)
395
+	 *
396
+	 * @param EE_Base_Class $item
397
+	 * @param string        $column_name
398
+	 * @param string        $primary
399
+	 * @return string
400
+	 */
401
+	protected function handle_row_actions($item, $column_name, $primary)
402
+	{
403
+		foreach (class_parents($this) as $parent) {
404
+			if ($parent === 'WP_List_Table' && method_exists($parent, 'handle_row_actions')) {
405
+				return parent::handle_row_actions($item, $column_name, $primary);
406
+			}
407
+		}
408
+		return '';
409
+	}
410
+
411
+
412
+	/**
413
+	 * _get_bulk_actions
414
+	 * This is a wrapper called by WP_List_Table::get_bulk_actions()
415
+	 *
416
+	 * @access protected
417
+	 * @return array bulk_actions
418
+	 */
419
+	protected function _get_bulk_actions(): array
420
+	{
421
+		$actions = [];
422
+		// the _views property should have the bulk_actions, so let's go through and extract them into a properly
423
+		// formatted array for the wp_list_table();
424
+		foreach ($this->_views as $view => $args) {
425
+			if ($this->_view === $view && isset($args['bulk_action']) && is_array($args['bulk_action'])) {
426
+				// each bulk action will correspond with a admin page route, so we can check whatever the capability is
427
+				// for that page route and skip adding the bulk action if no access for the current logged in user.
428
+				foreach ($args['bulk_action'] as $route => $label) {
429
+					if ($this->_admin_page->check_user_access($route, true)) {
430
+						$actions[ $route ] = $label;
431
+					}
432
+				}
433
+			}
434
+		}
435
+		return $actions;
436
+	}
437
+
438
+
439
+	/**
440
+	 * Generate the table navigation above or below the table.
441
+	 * Overrides the parent table nav in WP_List_Table so we can hide the bulk action div if there are no bulk actions.
442
+	 *
443
+	 * @throws EE_Error
444
+	 * @since 4.9.44.rc.001
445
+	 */
446
+	public function display_tablenav($which)
447
+	{
448
+		if ('top' === $which) {
449
+			wp_nonce_field('bulk-' . $this->_args['plural']);
450
+		}
451
+		?>
452 452
         <div class="tablenav <?php echo esc_attr($which); ?>">
453 453
             <?php if ($this->_get_bulk_actions()) { ?>
454 454
                 <div class="alignleft actions bulkactions">
455 455
                     <?php $this->bulk_actions(); ?>
456 456
                 </div>
457 457
             <?php }
458
-            $this->extra_tablenav($which);
459
-            $this->pagination($which);
460
-            ?>
458
+			$this->extra_tablenav($which);
459
+			$this->pagination($which);
460
+			?>
461 461
 
462 462
             <br class="clear" />
463 463
         </div>
464 464
         <?php
465
-    }
466
-
467
-
468
-    /**
469
-     * _filters
470
-     * This receives the filters array from children _get_table_filters() and assembles the string including the filter
471
-     * button.
472
-     *
473
-     * @access private
474
-     * @return void  echos html showing filters
475
-     */
476
-    private function _filters()
477
-    {
478
-        $classname = get_class($this);
479
-        $filters   = apply_filters(
480
-            "FHEE__{$classname}__filters",
481
-            (array) $this->_get_table_filters(),
482
-            $this,
483
-            $this->_screen
484
-        );
485
-
486
-        if (empty($filters)) {
487
-            return;
488
-        }
489
-        foreach ($filters as $filter) {
490
-            echo wp_kses($filter, AllowedTags::getWithFormTags());
491
-        }
492
-        echo '
465
+	}
466
+
467
+
468
+	/**
469
+	 * _filters
470
+	 * This receives the filters array from children _get_table_filters() and assembles the string including the filter
471
+	 * button.
472
+	 *
473
+	 * @access private
474
+	 * @return void  echos html showing filters
475
+	 */
476
+	private function _filters()
477
+	{
478
+		$classname = get_class($this);
479
+		$filters   = apply_filters(
480
+			"FHEE__{$classname}__filters",
481
+			(array) $this->_get_table_filters(),
482
+			$this,
483
+			$this->_screen
484
+		);
485
+
486
+		if (empty($filters)) {
487
+			return;
488
+		}
489
+		foreach ($filters as $filter) {
490
+			echo wp_kses($filter, AllowedTags::getWithFormTags());
491
+		}
492
+		echo '
493 493
         <span class="ee-list-table-filters__submit-buttons">';
494
-        // add filter button at end
495
-        echo '<input type="submit" class="button button--secondary" value="'
496
-             . esc_html__('Filter', 'event_espresso')
497
-             . '" id="post-query-submit" />';
498
-        // add reset filters button at end
499
-        echo '<a class="button button--secondary"  href="'
500
-             . esc_url_raw($this->_admin_page->get_current_page_view_url())
501
-             . '">'
502
-             . esc_html__('Reset Filters', 'event_espresso')
503
-             . '</a>';
504
-        echo '
494
+		// add filter button at end
495
+		echo '<input type="submit" class="button button--secondary" value="'
496
+			 . esc_html__('Filter', 'event_espresso')
497
+			 . '" id="post-query-submit" />';
498
+		// add reset filters button at end
499
+		echo '<a class="button button--secondary"  href="'
500
+			 . esc_url_raw($this->_admin_page->get_current_page_view_url())
501
+			 . '">'
502
+			 . esc_html__('Reset Filters', 'event_espresso')
503
+			 . '</a>';
504
+		echo '
505 505
         </span>';
506
-    }
507
-
508
-
509
-    /**
510
-     * Callback for 'list_table_primary_column' WordPress filter
511
-     * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
512
-     * column when class is instantiated.
513
-     *
514
-     * @param string $column_name
515
-     * @return string
516
-     * @see WP_List_Table::get_primary_column_name
517
-     */
518
-    public function set_primary_column($column_name)
519
-    {
520
-        return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
521
-    }
522
-
523
-
524
-    /**
525
-     *
526
-     */
527
-    public function prepare_items()
528
-    {
529
-        $this->_set_column_info();
530
-        // $this->_column_headers = $this->get_column_info();
531
-        $total_items = $this->_all_data_count;
532
-        $this->process_bulk_action();
533
-
534
-        $this->items = $this->_data;
535
-        $this->set_pagination_args(
536
-            [
537
-                'total_items' => $total_items,
538
-                'per_page'    => $this->_per_page,
539
-                'total_pages' => ceil($total_items / $this->_per_page),
540
-            ]
541
-        );
542
-    }
543
-
544
-
545
-    /**
546
-     * @param object|array $item
547
-     * @return string html content for the column
548
-     */
549
-    protected function column_cb($item)
550
-    {
551
-        return '';
552
-    }
553
-
554
-
555
-    /**
556
-     * This column is the default for when there is no defined column method for a registered column.
557
-     * This can be overridden by child classes, but allows for hooking in for custom columns.
558
-     *
559
-     * @param EE_Base_Class $item
560
-     * @param string        $column_name The column being called.
561
-     * @return string html content for the column
562
-     */
563
-    public function column_default($item, $column_name)
564
-    {
565
-        /**
566
-         * Dynamic hook allowing for adding additional column content in this list table.
567
-         * Note that $this->screen->id is in the format
568
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
569
-         * table it is: event-espresso_page_espresso_messages.
570
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
571
-         * hook prefix ("event-espresso") will be different.
572
-         */
573
-        ob_start();
574
-        do_action(
575
-            'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
576
-            $item,
577
-            $this->_screen
578
-        );
579
-        return ob_get_clean();
580
-    }
581
-
582
-
583
-    /**
584
-     * Get a list of columns. The format is:
585
-     * 'internal-name' => 'Title'
586
-     *
587
-     * @return array
588
-     * @since  3.1.0
589
-     * @access public
590
-     * @abstract
591
-     */
592
-    public function get_columns()
593
-    {
594
-        /**
595
-         * Dynamic hook allowing for adding additional columns in this list table.
596
-         * Note that $this->screen->id is in the format
597
-         * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
598
-         * table it is: event-espresso_page_espresso_messages.
599
-         * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
600
-         * hook prefix ("event-espresso") will be different.
601
-         *
602
-         * @var array
603
-         */
604
-        return apply_filters('FHEE_manage_' . $this->screen->id . '_columns', $this->_columns, $this->_screen);
605
-    }
606
-
607
-
608
-    /**
609
-     * Get an associative array ( id => link ) with the list
610
-     * of views available on this table.
611
-     *
612
-     * @return array
613
-     * @since  3.1.0
614
-     * @access protected
615
-     */
616
-    public function get_views()
617
-    {
618
-        return $this->_views;
619
-    }
620
-
621
-
622
-    /**
623
-     * Generate the views html.
624
-     */
625
-    public function display_views()
626
-    {
627
-        $views           = $this->get_views();
628
-        $assembled_views = [];
629
-
630
-        if (empty($views)) {
631
-            return;
632
-        }
633
-        echo "<ul class='subsubsub'>\n";
634
-        foreach ($views as $view) {
635
-            $count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
636
-            if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
637
-                $filter = "<li";
638
-                $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
639
-                $filter .= ">";
640
-                $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
641
-                $filter .= '<span class="count">(' . $count . ')</span>';
642
-                $filter .= '</li>';
643
-                $assembled_views[ $view['slug'] ] = $filter;
644
-            }
645
-        }
646
-
647
-        echo ! empty($assembled_views)
648
-            ? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
649
-            : '';
650
-        echo "</ul>";
651
-    }
652
-
653
-
654
-    /**
655
-     * Generates content for a single row of the table
656
-     *
657
-     * @param EE_Base_Class $item The current item
658
-     * @since  4.1
659
-     * @access public
660
-     */
661
-    public function single_row($item)
662
-    {
663
-        $row_class = $this->_get_row_class($item);
664
-        echo '<tr class="' . esc_attr($row_class) . '">';
665
-        $this->single_row_columns($item); // already escaped
666
-        echo '</tr>';
667
-    }
668
-
669
-
670
-    /**
671
-     * This simply sets up the row class for the table rows.
672
-     * Allows for easier overriding of child methods for setting up sorting.
673
-     *
674
-     * @param EE_Base_Class $item the current item
675
-     * @return string
676
-     */
677
-    protected function _get_row_class($item)
678
-    {
679
-        static $row_class = '';
680
-        $row_class = ($row_class === '' ? 'alternate' : '');
681
-
682
-        $new_row_class = $row_class;
683
-
684
-        if (! empty($this->_ajax_sorting_callback)) {
685
-            $new_row_class .= ' rowsortable';
686
-        }
687
-
688
-        return $new_row_class;
689
-    }
690
-
691
-
692
-    /**
693
-     * @return array
694
-     */
695
-    public function get_sortable_columns()
696
-    {
697
-        return (array) $this->_sortable_columns;
698
-    }
699
-
700
-
701
-    /**
702
-     * @return string
703
-     */
704
-    public function get_ajax_sorting_callback()
705
-    {
706
-        return $this->_ajax_sorting_callback;
707
-    }
708
-
709
-
710
-    /**
711
-     * @return array
712
-     */
713
-    public function get_hidden_columns()
714
-    {
715
-        $user_id     = get_current_user_id();
716
-        $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
717
-        if (empty($has_default) && ! empty($this->_hidden_columns)) {
718
-            update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
719
-            update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
720
-        }
721
-        $ref = 'manage' . $this->screen->id . 'columnshidden';
722
-        return (array) get_user_option($ref, $user_id);
723
-    }
724
-
725
-
726
-    /**
727
-     * Generates the columns for a single row of the table.
728
-     * Overridden from wp_list_table so as to allow us to filter the column content for a given
729
-     * column.
730
-     *
731
-     * @param EE_Base_Class $item The current item
732
-     * @since 3.1.0
733
-     */
734
-    public function single_row_columns($item)
735
-    {
736
-        [$columns, $hidden, $sortable, $primary] = $this->get_column_info();
737
-
738
-        foreach ($columns as $column_name => $column_display_name) {
739
-
740
-            /**
741
-             * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
742
-             * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
743
-             */
744
-            $hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
745
-
746
-            $classes = $column_name . ' column-' . $column_name . $hidden_class;
747
-            if ($primary === $column_name) {
748
-                $classes .= ' has-row-actions column-primary';
749
-            }
750
-
751
-            $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
752
-
753
-            $class = 'class="' . esc_attr($classes) . '"';
754
-
755
-            $attributes = "{$class}{$data}";
756
-
757
-            if ($column_name === 'cb') {
758
-                echo '<th scope="row" class="check-column">';
759
-                echo apply_filters(
760
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
761
-                    $this->column_cb($item), // already escaped
762
-                    $item,
763
-                    $this
764
-                );
765
-                echo '</th>';
766
-            } elseif (method_exists($this, 'column_' . $column_name)) {
767
-                echo "<td $attributes>"; // already escaped
768
-                echo apply_filters(
769
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
770
-                    call_user_func([$this, 'column_' . $column_name], $item),
771
-                    $item,
772
-                    $this
773
-                );
774
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
775
-                echo "</td>";
776
-            } else {
777
-                echo "<td $attributes>"; // already escaped
778
-                echo apply_filters(
779
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
780
-                    $this->column_default($item, $column_name),
781
-                    $item,
782
-                    $column_name,
783
-                    $this
784
-                );
785
-                echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
786
-                echo "</td>";
787
-            }
788
-        }
789
-    }
790
-
791
-
792
-    /**
793
-     * Extra controls to be displayed between bulk actions and pagination
794
-     *
795
-     * @access public
796
-     * @param string $which
797
-     * @throws EE_Error
798
-     */
799
-    public function extra_tablenav($which)
800
-    {
801
-        if ($which === 'top') {
802
-            $this->_filters();
803
-            echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
804
-        } else {
805
-            echo '<div class="list-table-bottom-buttons alignleft actions">';
806
-            foreach ($this->_bottom_buttons as $type => $action) {
807
-                $route         = isset($action['route']) ? $action['route'] : '';
808
-                $extra_request = isset($action['extra_request']) ? $action['extra_request'] : '';
809
-                // already escaped
810
-                echo wp_kses($this->_admin_page->get_action_link_or_button(
811
-                    $route,
812
-                    $type,
813
-                    $extra_request,
814
-                    'button button--secondary'
815
-                ), AllowedTags::getWithFormTags());
816
-            }
817
-            do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
818
-            echo '</div>';
819
-        }
820
-    }
821
-
822
-
823
-    /**
824
-     * Get an associative array ( option_name => option_title ) with the list
825
-     * of bulk actions available on this table.
826
-     *
827
-     * @return array
828
-     * @since  3.1.0
829
-     * @access protected
830
-     */
831
-    public function get_bulk_actions()
832
-    {
833
-        return (array) $this->_get_bulk_actions();
834
-    }
835
-
836
-
837
-    /**
838
-     * Processing bulk actions.
839
-     */
840
-    public function process_bulk_action()
841
-    {
842
-        // this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
843
-        // reference in case there is a case where it gets used.
844
-    }
845
-
846
-
847
-    /**
848
-     * returns the EE admin page this list table is associated with
849
-     *
850
-     * @return EE_Admin_Page
851
-     */
852
-    public function get_admin_page()
853
-    {
854
-        return $this->_admin_page;
855
-    }
856
-
857
-
858
-    /**
859
-     * A "helper" function for all children to provide an html string of
860
-     * actions to output in their content.  It is preferable for child classes
861
-     * to use this method for generating their actions content so that it's
862
-     * filterable by plugins
863
-     *
864
-     * @param string        $action_container           what are the html container
865
-     *                                                  elements for this actions string?
866
-     * @param string        $action_class               What class is for the container
867
-     *                                                  element.
868
-     * @param string        $action_items               The contents for the action items
869
-     *                                                  container.  This is filtered before
870
-     *                                                  returned.
871
-     * @param string        $action_id                  What id (optional) is used for the
872
-     *                                                  container element.
873
-     * @param EE_Base_Class $item                       The object for the column displaying
874
-     *                                                  the actions.
875
-     * @return string The assembled action elements container.
876
-     */
877
-    protected function _action_string(
878
-        $action_items,
879
-        $item,
880
-        $action_container = 'ul',
881
-        $action_class = '',
882
-        $action_id = ''
883
-    ) {
884
-        $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
885
-        $action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
886
-        $open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
887
-        $close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
888
-        try {
889
-            $content = apply_filters(
890
-                'FHEE__EE_Admin_List_Table___action_string__action_items',
891
-                $action_items,
892
-                $item,
893
-                $this
894
-            );
895
-        } catch (Exception $e) {
896
-            if (WP_DEBUG) {
897
-                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
898
-            }
899
-            $content = $action_items;
900
-        }
901
-        return "{$open_tag}{$content}{$close_tag}";
902
-    }
903
-
904
-
905
-    /**
906
-     * @return string
907
-     */
908
-    protected function getReturnUrl()
909
-    {
910
-        $host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
911
-        $uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
912
-        return urlencode(esc_url_raw("//{$host}{$uri}"));
913
-    }
914
-
915
-
916
-    /**
917
-     * @param string $id
918
-     * @param string $content
919
-     * @param string $align     start (default), center, end
920
-     * @return string
921
-     * @since   $VID:$
922
-     */
923
-    protected function columnContent($id, $content, $align = 'start')
924
-    {
925
-        if (! isset($this->_columns[ $id ])) {
926
-            throw new DomainException('missing column id');
927
-        }
928
-        $heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
929
-        $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
930
-        $align = "ee-responsive-table-cell--{$align}";
931
-
932
-        $html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-{$id} {$align} ee-layout-row'>";
933
-        $html .= "<div class='ee-responsive-table-cell__heading'>{$heading}</div>";
934
-        $html .= "<div class='ee-responsive-table-cell__content ee-layout-row'>{$content}</div>";
935
-        $html .= "</div>";
936
-        return $html;
937
-    }
938
-
939
-
940
-    protected function actionsModalMenu($actions): string
941
-    {
942
-        return '
506
+	}
507
+
508
+
509
+	/**
510
+	 * Callback for 'list_table_primary_column' WordPress filter
511
+	 * If child EE_Admin_List_Table classes set the _primary_column property then that will be set as the primary
512
+	 * column when class is instantiated.
513
+	 *
514
+	 * @param string $column_name
515
+	 * @return string
516
+	 * @see WP_List_Table::get_primary_column_name
517
+	 */
518
+	public function set_primary_column($column_name)
519
+	{
520
+		return ! empty($this->_primary_column) ? $this->_primary_column : $column_name;
521
+	}
522
+
523
+
524
+	/**
525
+	 *
526
+	 */
527
+	public function prepare_items()
528
+	{
529
+		$this->_set_column_info();
530
+		// $this->_column_headers = $this->get_column_info();
531
+		$total_items = $this->_all_data_count;
532
+		$this->process_bulk_action();
533
+
534
+		$this->items = $this->_data;
535
+		$this->set_pagination_args(
536
+			[
537
+				'total_items' => $total_items,
538
+				'per_page'    => $this->_per_page,
539
+				'total_pages' => ceil($total_items / $this->_per_page),
540
+			]
541
+		);
542
+	}
543
+
544
+
545
+	/**
546
+	 * @param object|array $item
547
+	 * @return string html content for the column
548
+	 */
549
+	protected function column_cb($item)
550
+	{
551
+		return '';
552
+	}
553
+
554
+
555
+	/**
556
+	 * This column is the default for when there is no defined column method for a registered column.
557
+	 * This can be overridden by child classes, but allows for hooking in for custom columns.
558
+	 *
559
+	 * @param EE_Base_Class $item
560
+	 * @param string        $column_name The column being called.
561
+	 * @return string html content for the column
562
+	 */
563
+	public function column_default($item, $column_name)
564
+	{
565
+		/**
566
+		 * Dynamic hook allowing for adding additional column content in this list table.
567
+		 * Note that $this->screen->id is in the format
568
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
569
+		 * table it is: event-espresso_page_espresso_messages.
570
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
571
+		 * hook prefix ("event-espresso") will be different.
572
+		 */
573
+		ob_start();
574
+		do_action(
575
+			'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
576
+			$item,
577
+			$this->_screen
578
+		);
579
+		return ob_get_clean();
580
+	}
581
+
582
+
583
+	/**
584
+	 * Get a list of columns. The format is:
585
+	 * 'internal-name' => 'Title'
586
+	 *
587
+	 * @return array
588
+	 * @since  3.1.0
589
+	 * @access public
590
+	 * @abstract
591
+	 */
592
+	public function get_columns()
593
+	{
594
+		/**
595
+		 * Dynamic hook allowing for adding additional columns in this list table.
596
+		 * Note that $this->screen->id is in the format
597
+		 * {sanitize_title($top_level_menu_label)}_page_{$espresso_admin_page_slug}.  So for the messages list
598
+		 * table it is: event-espresso_page_espresso_messages.
599
+		 * However, take note that if the top level menu label has been translated (i.e. "Event Espresso"). then the
600
+		 * hook prefix ("event-espresso") will be different.
601
+		 *
602
+		 * @var array
603
+		 */
604
+		return apply_filters('FHEE_manage_' . $this->screen->id . '_columns', $this->_columns, $this->_screen);
605
+	}
606
+
607
+
608
+	/**
609
+	 * Get an associative array ( id => link ) with the list
610
+	 * of views available on this table.
611
+	 *
612
+	 * @return array
613
+	 * @since  3.1.0
614
+	 * @access protected
615
+	 */
616
+	public function get_views()
617
+	{
618
+		return $this->_views;
619
+	}
620
+
621
+
622
+	/**
623
+	 * Generate the views html.
624
+	 */
625
+	public function display_views()
626
+	{
627
+		$views           = $this->get_views();
628
+		$assembled_views = [];
629
+
630
+		if (empty($views)) {
631
+			return;
632
+		}
633
+		echo "<ul class='subsubsub'>\n";
634
+		foreach ($views as $view) {
635
+			$count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
636
+			if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
637
+				$filter = "<li";
638
+				$filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
639
+				$filter .= ">";
640
+				$filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
641
+				$filter .= '<span class="count">(' . $count . ')</span>';
642
+				$filter .= '</li>';
643
+				$assembled_views[ $view['slug'] ] = $filter;
644
+			}
645
+		}
646
+
647
+		echo ! empty($assembled_views)
648
+			? implode("<li style='margin:0 .5rem;'>|</li>", $assembled_views)
649
+			: '';
650
+		echo "</ul>";
651
+	}
652
+
653
+
654
+	/**
655
+	 * Generates content for a single row of the table
656
+	 *
657
+	 * @param EE_Base_Class $item The current item
658
+	 * @since  4.1
659
+	 * @access public
660
+	 */
661
+	public function single_row($item)
662
+	{
663
+		$row_class = $this->_get_row_class($item);
664
+		echo '<tr class="' . esc_attr($row_class) . '">';
665
+		$this->single_row_columns($item); // already escaped
666
+		echo '</tr>';
667
+	}
668
+
669
+
670
+	/**
671
+	 * This simply sets up the row class for the table rows.
672
+	 * Allows for easier overriding of child methods for setting up sorting.
673
+	 *
674
+	 * @param EE_Base_Class $item the current item
675
+	 * @return string
676
+	 */
677
+	protected function _get_row_class($item)
678
+	{
679
+		static $row_class = '';
680
+		$row_class = ($row_class === '' ? 'alternate' : '');
681
+
682
+		$new_row_class = $row_class;
683
+
684
+		if (! empty($this->_ajax_sorting_callback)) {
685
+			$new_row_class .= ' rowsortable';
686
+		}
687
+
688
+		return $new_row_class;
689
+	}
690
+
691
+
692
+	/**
693
+	 * @return array
694
+	 */
695
+	public function get_sortable_columns()
696
+	{
697
+		return (array) $this->_sortable_columns;
698
+	}
699
+
700
+
701
+	/**
702
+	 * @return string
703
+	 */
704
+	public function get_ajax_sorting_callback()
705
+	{
706
+		return $this->_ajax_sorting_callback;
707
+	}
708
+
709
+
710
+	/**
711
+	 * @return array
712
+	 */
713
+	public function get_hidden_columns()
714
+	{
715
+		$user_id     = get_current_user_id();
716
+		$has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
717
+		if (empty($has_default) && ! empty($this->_hidden_columns)) {
718
+			update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
719
+			update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
720
+		}
721
+		$ref = 'manage' . $this->screen->id . 'columnshidden';
722
+		return (array) get_user_option($ref, $user_id);
723
+	}
724
+
725
+
726
+	/**
727
+	 * Generates the columns for a single row of the table.
728
+	 * Overridden from wp_list_table so as to allow us to filter the column content for a given
729
+	 * column.
730
+	 *
731
+	 * @param EE_Base_Class $item The current item
732
+	 * @since 3.1.0
733
+	 */
734
+	public function single_row_columns($item)
735
+	{
736
+		[$columns, $hidden, $sortable, $primary] = $this->get_column_info();
737
+
738
+		foreach ($columns as $column_name => $column_display_name) {
739
+
740
+			/**
741
+			 * With WordPress version 4.3.RC+ WordPress started using the hidden css class to control whether columns
742
+			 * are hidden or not instead of using "display:none;".  This bit of code provides backward compat.
743
+			 */
744
+			$hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
745
+
746
+			$classes = $column_name . ' column-' . $column_name . $hidden_class;
747
+			if ($primary === $column_name) {
748
+				$classes .= ' has-row-actions column-primary';
749
+			}
750
+
751
+			$data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
752
+
753
+			$class = 'class="' . esc_attr($classes) . '"';
754
+
755
+			$attributes = "{$class}{$data}";
756
+
757
+			if ($column_name === 'cb') {
758
+				echo '<th scope="row" class="check-column">';
759
+				echo apply_filters(
760
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_cb_content',
761
+					$this->column_cb($item), // already escaped
762
+					$item,
763
+					$this
764
+				);
765
+				echo '</th>';
766
+			} elseif (method_exists($this, 'column_' . $column_name)) {
767
+				echo "<td $attributes>"; // already escaped
768
+				echo apply_filters(
769
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
770
+					call_user_func([$this, 'column_' . $column_name], $item),
771
+					$item,
772
+					$this
773
+				);
774
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
775
+				echo "</td>";
776
+			} else {
777
+				echo "<td $attributes>"; // already escaped
778
+				echo apply_filters(
779
+					'FHEE__EE_Admin_List_Table__single_row_columns__column_default__column_content',
780
+					$this->column_default($item, $column_name),
781
+					$item,
782
+					$column_name,
783
+					$this
784
+				);
785
+				echo wp_kses($this->handle_row_actions($item, $column_name, $primary), AllowedTags::getWithFormTags());
786
+				echo "</td>";
787
+			}
788
+		}
789
+	}
790
+
791
+
792
+	/**
793
+	 * Extra controls to be displayed between bulk actions and pagination
794
+	 *
795
+	 * @access public
796
+	 * @param string $which
797
+	 * @throws EE_Error
798
+	 */
799
+	public function extra_tablenav($which)
800
+	{
801
+		if ($which === 'top') {
802
+			$this->_filters();
803
+			echo wp_kses($this->_get_hidden_fields(), AllowedTags::getWithFormTags());
804
+		} else {
805
+			echo '<div class="list-table-bottom-buttons alignleft actions">';
806
+			foreach ($this->_bottom_buttons as $type => $action) {
807
+				$route         = isset($action['route']) ? $action['route'] : '';
808
+				$extra_request = isset($action['extra_request']) ? $action['extra_request'] : '';
809
+				// already escaped
810
+				echo wp_kses($this->_admin_page->get_action_link_or_button(
811
+					$route,
812
+					$type,
813
+					$extra_request,
814
+					'button button--secondary'
815
+				), AllowedTags::getWithFormTags());
816
+			}
817
+			do_action('AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', $this, $this->_screen);
818
+			echo '</div>';
819
+		}
820
+	}
821
+
822
+
823
+	/**
824
+	 * Get an associative array ( option_name => option_title ) with the list
825
+	 * of bulk actions available on this table.
826
+	 *
827
+	 * @return array
828
+	 * @since  3.1.0
829
+	 * @access protected
830
+	 */
831
+	public function get_bulk_actions()
832
+	{
833
+		return (array) $this->_get_bulk_actions();
834
+	}
835
+
836
+
837
+	/**
838
+	 * Processing bulk actions.
839
+	 */
840
+	public function process_bulk_action()
841
+	{
842
+		// this is not used it is handled by the child EE_Admin_Page class (routes).  However, including here for
843
+		// reference in case there is a case where it gets used.
844
+	}
845
+
846
+
847
+	/**
848
+	 * returns the EE admin page this list table is associated with
849
+	 *
850
+	 * @return EE_Admin_Page
851
+	 */
852
+	public function get_admin_page()
853
+	{
854
+		return $this->_admin_page;
855
+	}
856
+
857
+
858
+	/**
859
+	 * A "helper" function for all children to provide an html string of
860
+	 * actions to output in their content.  It is preferable for child classes
861
+	 * to use this method for generating their actions content so that it's
862
+	 * filterable by plugins
863
+	 *
864
+	 * @param string        $action_container           what are the html container
865
+	 *                                                  elements for this actions string?
866
+	 * @param string        $action_class               What class is for the container
867
+	 *                                                  element.
868
+	 * @param string        $action_items               The contents for the action items
869
+	 *                                                  container.  This is filtered before
870
+	 *                                                  returned.
871
+	 * @param string        $action_id                  What id (optional) is used for the
872
+	 *                                                  container element.
873
+	 * @param EE_Base_Class $item                       The object for the column displaying
874
+	 *                                                  the actions.
875
+	 * @return string The assembled action elements container.
876
+	 */
877
+	protected function _action_string(
878
+		$action_items,
879
+		$item,
880
+		$action_container = 'ul',
881
+		$action_class = '',
882
+		$action_id = ''
883
+	) {
884
+		$action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
885
+		$action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
886
+		$open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
887
+		$close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
888
+		try {
889
+			$content = apply_filters(
890
+				'FHEE__EE_Admin_List_Table___action_string__action_items',
891
+				$action_items,
892
+				$item,
893
+				$this
894
+			);
895
+		} catch (Exception $e) {
896
+			if (WP_DEBUG) {
897
+				EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
898
+			}
899
+			$content = $action_items;
900
+		}
901
+		return "{$open_tag}{$content}{$close_tag}";
902
+	}
903
+
904
+
905
+	/**
906
+	 * @return string
907
+	 */
908
+	protected function getReturnUrl()
909
+	{
910
+		$host = $this->_admin_page->get_request()->getServerParam('HTTP_HOST');
911
+		$uri  = $this->_admin_page->get_request()->getServerParam('REQUEST_URI');
912
+		return urlencode(esc_url_raw("//{$host}{$uri}"));
913
+	}
914
+
915
+
916
+	/**
917
+	 * @param string $id
918
+	 * @param string $content
919
+	 * @param string $align     start (default), center, end
920
+	 * @return string
921
+	 * @since   $VID:$
922
+	 */
923
+	protected function columnContent($id, $content, $align = 'start')
924
+	{
925
+		if (! isset($this->_columns[ $id ])) {
926
+			throw new DomainException('missing column id');
927
+		}
928
+		$heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
929
+		$align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
930
+		$align = "ee-responsive-table-cell--{$align}";
931
+
932
+		$html = "<div class='ee-responsive-table-cell ee-responsive-table-cell--column-{$id} {$align} ee-layout-row'>";
933
+		$html .= "<div class='ee-responsive-table-cell__heading'>{$heading}</div>";
934
+		$html .= "<div class='ee-responsive-table-cell__content ee-layout-row'>{$content}</div>";
935
+		$html .= "</div>";
936
+		return $html;
937
+	}
938
+
939
+
940
+	protected function actionsModalMenu($actions): string
941
+	{
942
+		return '
943 943
         <div class="ee-modal-menu">
944 944
             <button class="ee-modal-menu__button button button--small button--icon-only ee-aria-tooltip"
945 945
                     aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '"
@@ -951,24 +951,24 @@  discard block
 block discarded – undo
951 951
                 ' . $actions . '
952 952
             </div>
953 953
         </div>';
954
-    }
954
+	}
955 955
 
956 956
 
957
-    protected function actionsColumnHeader(): string
958
-    {
959
-        return '
957
+	protected function actionsColumnHeader(): string
958
+	{
959
+		return '
960 960
             <span class="ee-actions-column-header-wrap">
961 961
                 <span class="dashicons dashicons-screenoptions"></span>
962 962
                 <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span>
963 963
             </span>';
964
-    }
964
+	}
965 965
 
966 966
 
967
-    protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
968
-    {
969
-        $class = ! empty($class) ? "{$class} ee-list-table-action" : 'ee-list-table-action';
970
-        $class = ! empty($label) ? "{$class} ee-aria-tooltip" : $class;
971
-        $label = ! empty($label) ? " aria-label='{$label}'" : '';
972
-        return "<a href='{$url}' class='{$class}'{$label}>{$display_text}</a>";
973
-    }
967
+	protected function getActionLink(string $url, string $display_text, string $label, $class = ''): string
968
+	{
969
+		$class = ! empty($class) ? "{$class} ee-list-table-action" : 'ee-list-table-action';
970
+		$class = ! empty($label) ? "{$class} ee-aria-tooltip" : $class;
971
+		$label = ! empty($label) ? " aria-label='{$label}'" : '';
972
+		return "<a href='{$url}' class='{$class}'{$label}>{$display_text}</a>";
973
+	}
974 974
 }
Please login to merge, or discard this patch.
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -2,8 +2,8 @@  discard block
 block discarded – undo
2 2
 
3 3
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
4 4
 
5
-if (! class_exists('WP_List_Table')) {
6
-    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
5
+if ( ! class_exists('WP_List_Table')) {
6
+    require_once ABSPATH.'wp-admin/includes/class-wp-list-table.php';
7 7
 }
8 8
 
9 9
 
@@ -223,13 +223,13 @@  discard block
 block discarded – undo
223 223
         $this->_view         = $this->_admin_page->get_view();
224 224
         $this->_views        = empty($this->_views) ? $this->_admin_page->get_list_table_view_RLs() : $this->_views;
225 225
         $this->_current_page = $this->get_pagenum();
226
-        $this->_screen       = $this->_admin_page->get_current_page() . '_' . $this->_admin_page->get_current_view();
226
+        $this->_screen       = $this->_admin_page->get_current_page().'_'.$this->_admin_page->get_current_view();
227 227
         $this->_yes_no       = [
228 228
             esc_html__('No', 'event_espresso'),
229 229
             esc_html__('Yes', 'event_espresso')
230 230
         ];
231 231
 
232
-        $this->_per_page = $this->get_items_per_page($this->_screen . '_per_page');
232
+        $this->_per_page = $this->get_items_per_page($this->_screen.'_per_page');
233 233
 
234 234
         $this->_setup_data();
235 235
         $this->_add_view_counts();
@@ -309,14 +309,14 @@  discard block
 block discarded – undo
309 309
         $action = empty($action) && isset($this->_req_data['action']) ? $this->_req_data['action'] : $action;
310 310
         // if action is STILL empty, then we set it to default
311 311
         $action = empty($action) ? 'default' : $action;
312
-        $field  = '<input type="hidden" name="page" value="' . esc_attr($this->_req_data['page']) . '" />' . "\n";
313
-        $field  .= '<input type="hidden" name="route" value="' . esc_attr($action) . '" />' . "\n";
314
-        $field  .= '<input type="hidden" name="perpage" value="' . esc_attr($this->_per_page) . '" />' . "\n";
312
+        $field  = '<input type="hidden" name="page" value="'.esc_attr($this->_req_data['page']).'" />'."\n";
313
+        $field  .= '<input type="hidden" name="route" value="'.esc_attr($action).'" />'."\n";
314
+        $field  .= '<input type="hidden" name="perpage" value="'.esc_attr($this->_per_page).'" />'."\n";
315 315
 
316 316
         $bulk_actions = $this->_get_bulk_actions();
317 317
         foreach ($bulk_actions as $bulk_action => $label) {
318
-            $field .= '<input type="hidden" name="' . $bulk_action . '_nonce"'
319
-                      . ' value="' . wp_create_nonce($bulk_action . '_nonce') . '" />' . "\n";
318
+            $field .= '<input type="hidden" name="'.$bulk_action.'_nonce"'
319
+                      . ' value="'.wp_create_nonce($bulk_action.'_nonce').'" />'."\n";
320 320
         }
321 321
 
322 322
         return $field;
@@ -363,11 +363,11 @@  discard block
 block discarded – undo
363 363
 
364 364
             $data = (array) $data;
365 365
 
366
-            if (! isset($data[1])) {
366
+            if ( ! isset($data[1])) {
367 367
                 $_data[1] = false;
368 368
             }
369 369
 
370
-            $sortable[ $id ] = $_data;
370
+            $sortable[$id] = $_data;
371 371
         }
372 372
         $primary               = $this->get_primary_column_name();
373 373
         $this->_column_headers = [$columns, $hidden, $sortable, $primary];
@@ -427,7 +427,7 @@  discard block
 block discarded – undo
427 427
                 // for that page route and skip adding the bulk action if no access for the current logged in user.
428 428
                 foreach ($args['bulk_action'] as $route => $label) {
429 429
                     if ($this->_admin_page->check_user_access($route, true)) {
430
-                        $actions[ $route ] = $label;
430
+                        $actions[$route] = $label;
431 431
                     }
432 432
                 }
433 433
             }
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
     public function display_tablenav($which)
447 447
     {
448 448
         if ('top' === $which) {
449
-            wp_nonce_field('bulk-' . $this->_args['plural']);
449
+            wp_nonce_field('bulk-'.$this->_args['plural']);
450 450
         }
451 451
         ?>
452 452
         <div class="tablenav <?php echo esc_attr($which); ?>">
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
          */
573 573
         ob_start();
574 574
         do_action(
575
-            'AHEE__EE_Admin_List_Table__column_' . $column_name . '__' . $this->screen->id,
575
+            'AHEE__EE_Admin_List_Table__column_'.$column_name.'__'.$this->screen->id,
576 576
             $item,
577 577
             $this->_screen
578 578
         );
@@ -601,7 +601,7 @@  discard block
 block discarded – undo
601 601
          *
602 602
          * @var array
603 603
          */
604
-        return apply_filters('FHEE_manage_' . $this->screen->id . '_columns', $this->_columns, $this->_screen);
604
+        return apply_filters('FHEE_manage_'.$this->screen->id.'_columns', $this->_columns, $this->_screen);
605 605
     }
606 606
 
607 607
 
@@ -635,12 +635,12 @@  discard block
 block discarded – undo
635 635
             $count = isset($view['count']) && ! empty($view['count']) ? absint($view['count']) : 0;
636 636
             if (isset($view['slug'], $view['class'], $view['url'], $view['label'])) {
637 637
                 $filter = "<li";
638
-                $filter .= $view['class'] ? " class='" . esc_attr($view['class']) . "'" : '';
638
+                $filter .= $view['class'] ? " class='".esc_attr($view['class'])."'" : '';
639 639
                 $filter .= ">";
640
-                $filter .= '<a href="' . esc_url_raw($view['url']) . '">' . esc_html($view['label']) . '</a>';
641
-                $filter .= '<span class="count">(' . $count . ')</span>';
640
+                $filter .= '<a href="'.esc_url_raw($view['url']).'">'.esc_html($view['label']).'</a>';
641
+                $filter .= '<span class="count">('.$count.')</span>';
642 642
                 $filter .= '</li>';
643
-                $assembled_views[ $view['slug'] ] = $filter;
643
+                $assembled_views[$view['slug']] = $filter;
644 644
             }
645 645
         }
646 646
 
@@ -661,7 +661,7 @@  discard block
 block discarded – undo
661 661
     public function single_row($item)
662 662
     {
663 663
         $row_class = $this->_get_row_class($item);
664
-        echo '<tr class="' . esc_attr($row_class) . '">';
664
+        echo '<tr class="'.esc_attr($row_class).'">';
665 665
         $this->single_row_columns($item); // already escaped
666 666
         echo '</tr>';
667 667
     }
@@ -681,7 +681,7 @@  discard block
 block discarded – undo
681 681
 
682 682
         $new_row_class = $row_class;
683 683
 
684
-        if (! empty($this->_ajax_sorting_callback)) {
684
+        if ( ! empty($this->_ajax_sorting_callback)) {
685 685
             $new_row_class .= ' rowsortable';
686 686
         }
687 687
 
@@ -713,12 +713,12 @@  discard block
 block discarded – undo
713 713
     public function get_hidden_columns()
714 714
     {
715 715
         $user_id     = get_current_user_id();
716
-        $has_default = get_user_option('default' . $this->screen->id . 'columnshidden', $user_id);
716
+        $has_default = get_user_option('default'.$this->screen->id.'columnshidden', $user_id);
717 717
         if (empty($has_default) && ! empty($this->_hidden_columns)) {
718
-            update_user_option($user_id, 'default' . $this->screen->id . 'columnshidden', true);
719
-            update_user_option($user_id, 'manage' . $this->screen->id . 'columnshidden', $this->_hidden_columns, true);
718
+            update_user_option($user_id, 'default'.$this->screen->id.'columnshidden', true);
719
+            update_user_option($user_id, 'manage'.$this->screen->id.'columnshidden', $this->_hidden_columns, true);
720 720
         }
721
-        $ref = 'manage' . $this->screen->id . 'columnshidden';
721
+        $ref = 'manage'.$this->screen->id.'columnshidden';
722 722
         return (array) get_user_option($ref, $user_id);
723 723
     }
724 724
 
@@ -743,14 +743,14 @@  discard block
 block discarded – undo
743 743
              */
744 744
             $hidden_class = in_array($column_name, $hidden) ? ' hidden' : '';
745 745
 
746
-            $classes = $column_name . ' column-' . $column_name . $hidden_class;
746
+            $classes = $column_name.' column-'.$column_name.$hidden_class;
747 747
             if ($primary === $column_name) {
748 748
                 $classes .= ' has-row-actions column-primary';
749 749
             }
750 750
 
751
-            $data = ' data-colname="' . wp_strip_all_tags($column_display_name) . '"';
751
+            $data = ' data-colname="'.wp_strip_all_tags($column_display_name).'"';
752 752
 
753
-            $class = 'class="' . esc_attr($classes) . '"';
753
+            $class = 'class="'.esc_attr($classes).'"';
754 754
 
755 755
             $attributes = "{$class}{$data}";
756 756
 
@@ -763,11 +763,11 @@  discard block
 block discarded – undo
763 763
                     $this
764 764
                 );
765 765
                 echo '</th>';
766
-            } elseif (method_exists($this, 'column_' . $column_name)) {
766
+            } elseif (method_exists($this, 'column_'.$column_name)) {
767 767
                 echo "<td $attributes>"; // already escaped
768 768
                 echo apply_filters(
769
-                    'FHEE__EE_Admin_List_Table__single_row_columns__column_' . $column_name . '__column_content',
770
-                    call_user_func([$this, 'column_' . $column_name], $item),
769
+                    'FHEE__EE_Admin_List_Table__single_row_columns__column_'.$column_name.'__column_content',
770
+                    call_user_func([$this, 'column_'.$column_name], $item),
771 771
                     $item,
772 772
                     $this
773 773
                 );
@@ -881,10 +881,10 @@  discard block
 block discarded – undo
881 881
         $action_class = '',
882 882
         $action_id = ''
883 883
     ) {
884
-        $action_class = ! empty($action_class) ? ' class="' . esc_attr($action_class) . '"' : '';
885
-        $action_id    = ! empty($action_id) ? ' id="' . esc_attr($action_id) . '"' : '';
886
-        $open_tag     = ! empty($action_container) ? '<' . $action_container . $action_class . $action_id . '>' : '';
887
-        $close_tag    = ! empty($action_container) ? '</' . $action_container . '>' : '';
884
+        $action_class = ! empty($action_class) ? ' class="'.esc_attr($action_class).'"' : '';
885
+        $action_id    = ! empty($action_id) ? ' id="'.esc_attr($action_id).'"' : '';
886
+        $open_tag     = ! empty($action_container) ? '<'.$action_container.$action_class.$action_id.'>' : '';
887
+        $close_tag    = ! empty($action_container) ? '</'.$action_container.'>' : '';
888 888
         try {
889 889
             $content = apply_filters(
890 890
                 'FHEE__EE_Admin_List_Table___action_string__action_items',
@@ -922,10 +922,10 @@  discard block
 block discarded – undo
922 922
      */
923 923
     protected function columnContent($id, $content, $align = 'start')
924 924
     {
925
-        if (! isset($this->_columns[ $id ])) {
925
+        if ( ! isset($this->_columns[$id])) {
926 926
             throw new DomainException('missing column id');
927 927
         }
928
-        $heading = $id !== 'cb' ? $this->_columns[ $id ] : '';
928
+        $heading = $id !== 'cb' ? $this->_columns[$id] : '';
929 929
         $align = in_array($align, ['start', 'center', 'end']) ? $align : 'start';
930 930
         $align = "ee-responsive-table-cell--{$align}";
931 931
 
@@ -942,13 +942,13 @@  discard block
 block discarded – undo
942 942
         return '
943 943
         <div class="ee-modal-menu">
944 944
             <button class="ee-modal-menu__button button button--small button--icon-only ee-aria-tooltip"
945
-                    aria-label="' . esc_attr__('list table actions menu', 'event_espresso') . '"
945
+                    aria-label="' . esc_attr__('list table actions menu', 'event_espresso').'"
946 946
             >
947 947
                 <span class="dashicons dashicons-menu"></span>
948 948
             </button>
949 949
             <div class="ee-modal-menu__content ee-admin-container">
950 950
                 <span class="ee-modal-menu__close dashicons dashicons-no"></span>
951
-                ' . $actions . '
951
+                ' . $actions.'
952 952
             </div>
953 953
         </div>';
954 954
     }
@@ -959,7 +959,7 @@  discard block
 block discarded – undo
959 959
         return '
960 960
             <span class="ee-actions-column-header-wrap">
961 961
                 <span class="dashicons dashicons-screenoptions"></span>
962
-                <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso') . '</span>
962
+                <span class="ee-actions-column-header">' . esc_html__('Actions', 'event_espresso').'</span>
963 963
             </span>';
964 964
     }
965 965
 
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_CPT.core.php 2 patches
Indentation   +1463 added lines, -1463 removed lines patch added patch discarded remove patch
@@ -27,481 +27,481 @@  discard block
 block discarded – undo
27 27
  */
28 28
 abstract class EE_Admin_Page_CPT extends EE_Admin_Page
29 29
 {
30
-    /**
31
-     * This gets set in _setup_cpt
32
-     * It will contain the object for the custom post type.
33
-     *
34
-     * @var EE_CPT_Base
35
-     */
36
-    protected $_cpt_object;
37
-
38
-
39
-    /**
40
-     * a boolean flag to set whether the current route is a cpt route or not.
41
-     *
42
-     * @var bool
43
-     */
44
-    protected $_cpt_route = false;
45
-
46
-
47
-    /**
48
-     * This property allows cpt classes to define multiple routes as cpt routes.
49
-     * //in this array we define what the custom post type for this route is.
50
-     * array(
51
-     * 'route_name' => 'custom_post_type_slug'
52
-     * )
53
-     *
54
-     * @var array
55
-     */
56
-    protected $_cpt_routes = [];
57
-
58
-
59
-    /**
60
-     * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
61
-     * in this format:
62
-     * array(
63
-     * 'post_type_slug' => 'edit_route'
64
-     * )
65
-     *
66
-     * @var array
67
-     */
68
-    protected $_cpt_edit_routes = [];
69
-
70
-
71
-    /**
72
-     * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
73
-     * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
74
-     * _cpt_model_names property should be in the following format: array(
75
-     * 'route_defined_by_action_param' => 'Model_Name')
76
-     *
77
-     * @var array $_cpt_model_names
78
-     */
79
-    protected $_cpt_model_names = [];
80
-
81
-
82
-    /**
83
-     * @var EE_CPT_Base
84
-     */
85
-    protected $_cpt_model_obj = false;
86
-
87
-
88
-    /**
89
-     * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
90
-     * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
91
-     * the _register_autosave_containers() method so that we don't override any other containers already registered.
92
-     * Registration of containers should be done before load_page_dependencies() is run.
93
-     *
94
-     * @var array()
95
-     */
96
-    protected $_autosave_containers = [];
97
-
98
-    protected $_autosave_fields     = [];
99
-
100
-    /**
101
-     * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
102
-     * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
103
-     *
104
-     * @var array
105
-     */
106
-    protected $_pagenow_map;
107
-
108
-
109
-
110
-    /**
111
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
112
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
113
-     * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
114
-     * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
115
-     * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
116
-     *
117
-     * @abstract
118
-     * @param string      $post_id The ID of the cpt that was saved (so you can link relationally)
119
-     * @param WP_Post     $post    The post object of the cpt that was saved.
120
-     * @return void
121
-     */
122
-    abstract protected function _insert_update_cpt_item($post_id, $post);
123
-
124
-
125
-    /**
126
-     * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
127
-     *
128
-     * @abstract
129
-     * @param string $post_id The ID of the cpt that was trashed
130
-     * @return void
131
-     */
132
-    abstract public function trash_cpt_item($post_id);
133
-
134
-
135
-    /**
136
-     * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
137
-     *
138
-     * @param string $post_id theID of the cpt that was untrashed
139
-     * @return void
140
-     */
141
-    abstract public function restore_cpt_item($post_id);
142
-
143
-
144
-    /**
145
-     * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
146
-     * from the db
147
-     *
148
-     * @param string $post_id the ID of the cpt that was deleted
149
-     * @return void
150
-     */
151
-    abstract public function delete_cpt_item($post_id);
152
-
153
-
154
-    /**
155
-     * @return LoaderInterface
156
-     * @throws InvalidArgumentException
157
-     * @throws InvalidDataTypeException
158
-     * @throws InvalidInterfaceException
159
-     */
160
-    protected function getLoader()
161
-    {
162
-        if (! $this->loader instanceof LoaderInterface) {
163
-            $this->loader = LoaderFactory::getLoader();
164
-        }
165
-        return $this->loader;
166
-    }
167
-
168
-
169
-    /**
170
-     * Just utilizing the method EE_Admin exposes for doing things before page setup.
171
-     *
172
-     * @return void
173
-     */
174
-    protected function _before_page_setup()
175
-    {
176
-        $this->raw_req_action = $this->request->getRequestParam('action');
177
-        $this->raw_req_page = $this->request->getRequestParam('page');
178
-        $this->_cpt_routes = array_merge(
179
-            [
180
-                'create_new' => $this->page_slug,
181
-                'edit'       => $this->page_slug,
182
-                'trash'      => $this->page_slug,
183
-            ],
184
-            $this->_cpt_routes
185
-        );
186
-        $cpt_route_action  = isset($this->_cpt_routes[ $this->raw_req_action ])
187
-            ? $this->_cpt_routes[ $this->raw_req_action ]
188
-            : null;
189
-        // let's see if the current route has a value for cpt_object_slug. if it does, we use that instead of the page
190
-        $page              = $this->raw_req_page ?: $this->page_slug;
191
-        $page              = $cpt_route_action ?: $page;
192
-        $this->_cpt_object = get_post_type_object($page);
193
-        // tweak pagenow for page loading.
194
-        if (! $this->_pagenow_map) {
195
-            $this->_pagenow_map = [
196
-                'create_new' => 'post-new.php',
197
-                'edit'       => 'post.php',
198
-                'trash'      => 'post.php',
199
-            ];
200
-        }
201
-        add_action('current_screen', [$this, 'modify_pagenow']);
202
-        // TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
203
-        // get current page from autosave
204
-        $current_page        = $this->request->getRequestParam('ee_autosave_data[ee-cpt-hidden-inputs][current_page]');
205
-        $this->_current_page = $this->request->getRequestParam('current_page', $current_page);
206
-    }
207
-
208
-
209
-    /**
210
-     * Simply ensure that we simulate the correct post route for cpt screens
211
-     *
212
-     * @param WP_Screen $current_screen
213
-     * @return void
214
-     */
215
-    public function modify_pagenow($current_screen)
216
-    {
217
-        // possibly reset pagenow.
218
-        if (
219
-            $this->page_slug === $this->raw_req_page
220
-            && isset($this->_pagenow_map[ $this->raw_req_action ])
221
-        ) {
222
-            global $pagenow, $hook_suffix;
223
-            $pagenow     = $this->_pagenow_map[ $this->raw_req_action ];
224
-            $hook_suffix = $pagenow;
225
-        }
226
-    }
227
-
228
-
229
-    /**
230
-     * This method is used to register additional autosave containers to the _autosave_containers property.
231
-     *
232
-     * @param array $ids  an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
233
-     *                    you would send along the id of a metabox container.
234
-     * @return void
235
-     * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
236
-     *                    automatically register the id for the post metabox as a container.
237
-     */
238
-    protected function _register_autosave_containers($ids)
239
-    {
240
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
241
-    }
242
-
243
-
244
-    /**
245
-     * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
246
-     * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
247
-     */
248
-    protected function _set_autosave_containers()
249
-    {
250
-        global $wp_meta_boxes;
251
-        $containers = [];
252
-        if (empty($wp_meta_boxes)) {
253
-            return;
254
-        }
255
-        $current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : [];
256
-        foreach ($current_metaboxes as $box_context) {
257
-            foreach ($box_context as $box_details) {
258
-                foreach ($box_details as $box) {
259
-                    if (
260
-                        is_array($box) && is_array($box['callback'])
261
-                        && (
262
-                            $box['callback'][0] instanceof EE_Admin_Page
263
-                            || $box['callback'][0] instanceof EE_Admin_Hooks
264
-                        )
265
-                    ) {
266
-                        $containers[] = $box['id'];
267
-                    }
268
-                }
269
-            }
270
-        }
271
-        $this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
272
-        // add hidden inputs container
273
-        $this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
274
-    }
275
-
276
-
277
-    protected function _load_autosave_scripts_styles()
278
-    {
279
-        /*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
30
+	/**
31
+	 * This gets set in _setup_cpt
32
+	 * It will contain the object for the custom post type.
33
+	 *
34
+	 * @var EE_CPT_Base
35
+	 */
36
+	protected $_cpt_object;
37
+
38
+
39
+	/**
40
+	 * a boolean flag to set whether the current route is a cpt route or not.
41
+	 *
42
+	 * @var bool
43
+	 */
44
+	protected $_cpt_route = false;
45
+
46
+
47
+	/**
48
+	 * This property allows cpt classes to define multiple routes as cpt routes.
49
+	 * //in this array we define what the custom post type for this route is.
50
+	 * array(
51
+	 * 'route_name' => 'custom_post_type_slug'
52
+	 * )
53
+	 *
54
+	 * @var array
55
+	 */
56
+	protected $_cpt_routes = [];
57
+
58
+
59
+	/**
60
+	 * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
61
+	 * in this format:
62
+	 * array(
63
+	 * 'post_type_slug' => 'edit_route'
64
+	 * )
65
+	 *
66
+	 * @var array
67
+	 */
68
+	protected $_cpt_edit_routes = [];
69
+
70
+
71
+	/**
72
+	 * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
73
+	 * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
74
+	 * _cpt_model_names property should be in the following format: array(
75
+	 * 'route_defined_by_action_param' => 'Model_Name')
76
+	 *
77
+	 * @var array $_cpt_model_names
78
+	 */
79
+	protected $_cpt_model_names = [];
80
+
81
+
82
+	/**
83
+	 * @var EE_CPT_Base
84
+	 */
85
+	protected $_cpt_model_obj = false;
86
+
87
+
88
+	/**
89
+	 * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
90
+	 * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
91
+	 * the _register_autosave_containers() method so that we don't override any other containers already registered.
92
+	 * Registration of containers should be done before load_page_dependencies() is run.
93
+	 *
94
+	 * @var array()
95
+	 */
96
+	protected $_autosave_containers = [];
97
+
98
+	protected $_autosave_fields     = [];
99
+
100
+	/**
101
+	 * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
102
+	 * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
103
+	 *
104
+	 * @var array
105
+	 */
106
+	protected $_pagenow_map;
107
+
108
+
109
+
110
+	/**
111
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
112
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
113
+	 * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
114
+	 * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
115
+	 * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
116
+	 *
117
+	 * @abstract
118
+	 * @param string      $post_id The ID of the cpt that was saved (so you can link relationally)
119
+	 * @param WP_Post     $post    The post object of the cpt that was saved.
120
+	 * @return void
121
+	 */
122
+	abstract protected function _insert_update_cpt_item($post_id, $post);
123
+
124
+
125
+	/**
126
+	 * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
127
+	 *
128
+	 * @abstract
129
+	 * @param string $post_id The ID of the cpt that was trashed
130
+	 * @return void
131
+	 */
132
+	abstract public function trash_cpt_item($post_id);
133
+
134
+
135
+	/**
136
+	 * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
137
+	 *
138
+	 * @param string $post_id theID of the cpt that was untrashed
139
+	 * @return void
140
+	 */
141
+	abstract public function restore_cpt_item($post_id);
142
+
143
+
144
+	/**
145
+	 * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
146
+	 * from the db
147
+	 *
148
+	 * @param string $post_id the ID of the cpt that was deleted
149
+	 * @return void
150
+	 */
151
+	abstract public function delete_cpt_item($post_id);
152
+
153
+
154
+	/**
155
+	 * @return LoaderInterface
156
+	 * @throws InvalidArgumentException
157
+	 * @throws InvalidDataTypeException
158
+	 * @throws InvalidInterfaceException
159
+	 */
160
+	protected function getLoader()
161
+	{
162
+		if (! $this->loader instanceof LoaderInterface) {
163
+			$this->loader = LoaderFactory::getLoader();
164
+		}
165
+		return $this->loader;
166
+	}
167
+
168
+
169
+	/**
170
+	 * Just utilizing the method EE_Admin exposes for doing things before page setup.
171
+	 *
172
+	 * @return void
173
+	 */
174
+	protected function _before_page_setup()
175
+	{
176
+		$this->raw_req_action = $this->request->getRequestParam('action');
177
+		$this->raw_req_page = $this->request->getRequestParam('page');
178
+		$this->_cpt_routes = array_merge(
179
+			[
180
+				'create_new' => $this->page_slug,
181
+				'edit'       => $this->page_slug,
182
+				'trash'      => $this->page_slug,
183
+			],
184
+			$this->_cpt_routes
185
+		);
186
+		$cpt_route_action  = isset($this->_cpt_routes[ $this->raw_req_action ])
187
+			? $this->_cpt_routes[ $this->raw_req_action ]
188
+			: null;
189
+		// let's see if the current route has a value for cpt_object_slug. if it does, we use that instead of the page
190
+		$page              = $this->raw_req_page ?: $this->page_slug;
191
+		$page              = $cpt_route_action ?: $page;
192
+		$this->_cpt_object = get_post_type_object($page);
193
+		// tweak pagenow for page loading.
194
+		if (! $this->_pagenow_map) {
195
+			$this->_pagenow_map = [
196
+				'create_new' => 'post-new.php',
197
+				'edit'       => 'post.php',
198
+				'trash'      => 'post.php',
199
+			];
200
+		}
201
+		add_action('current_screen', [$this, 'modify_pagenow']);
202
+		// TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
203
+		// get current page from autosave
204
+		$current_page        = $this->request->getRequestParam('ee_autosave_data[ee-cpt-hidden-inputs][current_page]');
205
+		$this->_current_page = $this->request->getRequestParam('current_page', $current_page);
206
+	}
207
+
208
+
209
+	/**
210
+	 * Simply ensure that we simulate the correct post route for cpt screens
211
+	 *
212
+	 * @param WP_Screen $current_screen
213
+	 * @return void
214
+	 */
215
+	public function modify_pagenow($current_screen)
216
+	{
217
+		// possibly reset pagenow.
218
+		if (
219
+			$this->page_slug === $this->raw_req_page
220
+			&& isset($this->_pagenow_map[ $this->raw_req_action ])
221
+		) {
222
+			global $pagenow, $hook_suffix;
223
+			$pagenow     = $this->_pagenow_map[ $this->raw_req_action ];
224
+			$hook_suffix = $pagenow;
225
+		}
226
+	}
227
+
228
+
229
+	/**
230
+	 * This method is used to register additional autosave containers to the _autosave_containers property.
231
+	 *
232
+	 * @param array $ids  an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
233
+	 *                    you would send along the id of a metabox container.
234
+	 * @return void
235
+	 * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
236
+	 *                    automatically register the id for the post metabox as a container.
237
+	 */
238
+	protected function _register_autosave_containers($ids)
239
+	{
240
+		$this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
241
+	}
242
+
243
+
244
+	/**
245
+	 * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
246
+	 * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
247
+	 */
248
+	protected function _set_autosave_containers()
249
+	{
250
+		global $wp_meta_boxes;
251
+		$containers = [];
252
+		if (empty($wp_meta_boxes)) {
253
+			return;
254
+		}
255
+		$current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : [];
256
+		foreach ($current_metaboxes as $box_context) {
257
+			foreach ($box_context as $box_details) {
258
+				foreach ($box_details as $box) {
259
+					if (
260
+						is_array($box) && is_array($box['callback'])
261
+						&& (
262
+							$box['callback'][0] instanceof EE_Admin_Page
263
+							|| $box['callback'][0] instanceof EE_Admin_Hooks
264
+						)
265
+					) {
266
+						$containers[] = $box['id'];
267
+					}
268
+				}
269
+			}
270
+		}
271
+		$this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
272
+		// add hidden inputs container
273
+		$this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
274
+	}
275
+
276
+
277
+	protected function _load_autosave_scripts_styles()
278
+	{
279
+		/*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
280 280
         wp_enqueue_script('cpt-autosave');/**/ // todo re-enable when we start doing autosave again in 4.2
281 281
 
282
-        // filter _autosave_containers
283
-        $containers = apply_filters(
284
-            'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
285
-            $this->_autosave_containers,
286
-            $this
287
-        );
288
-        $containers = apply_filters(
289
-            'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
290
-            $containers,
291
-            $this
292
-        );
293
-
294
-        wp_localize_script(
295
-            'event_editor_js',
296
-            'EE_AUTOSAVE_IDS',
297
-            $containers
298
-        ); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
299
-
300
-        $unsaved_data_msg = [
301
-            'eventmsg'     => sprintf(
302
-                wp_strip_all_tags(
303
-                    __(
304
-                        "The changes you made to this %s will be lost if you navigate away from this page.",
305
-                        'event_espresso'
306
-                    )
307
-                ),
308
-                $this->_cpt_object->labels->singular_name
309
-            ),
310
-            'inputChanged' => 0,
311
-        ];
312
-        wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
313
-    }
314
-
315
-
316
-    /**
317
-     * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
318
-     *
319
-     * @return void
320
-     * @throws EE_Error
321
-     * @throws ReflectionException
322
-     */
323
-    protected function _load_page_dependencies()
324
-    {
325
-        // we only add stuff if this is a cpt_route!
326
-        if (! $this->_cpt_route) {
327
-            parent::_load_page_dependencies();
328
-            return;
329
-        }
330
-        // now let's do some automatic filters into the wp_system
331
-        // and we'll check to make sure the CHILD class
332
-        // automatically has the required methods in place.
333
-        // the following filters are for setting all the redirects
334
-        // on DEFAULT WP custom post type actions
335
-        // let's add a hidden input to the post-edit form
336
-        // so we know when we have to trigger our custom redirects!
337
-        // Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
338
-        add_action('edit_form_after_title', [$this, 'cpt_post_form_hidden_input']);
339
-        // inject our Admin page nav tabs...
340
-        // let's make sure the nav tabs are set if they aren't already
341
-        // if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
342
-        add_action('edit_form_top', [$this, 'inject_nav_tabs']);
343
-        // modify the post_updated messages array
344
-        add_action('post_updated_messages', [$this, 'post_update_messages'], 10);
345
-        // add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
346
-        // cpts use the same format for shortlinks as posts!
347
-        add_filter('pre_get_shortlink', [$this, 'add_shortlink_button_to_editor'], 10, 4);
348
-        // This basically allows us to change the title of the "publish" metabox area
349
-        // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
350
-        if (! empty($this->_labels['publishbox'])) {
351
-            $box_label = is_array($this->_labels['publishbox'])
352
-                         && isset($this->_labels['publishbox'][ $this->_req_action ])
353
-                ? $this->_labels['publishbox'][ $this->_req_action ]
354
-                : $this->_labels['publishbox'];
355
-            $this->addMetaBox(
356
-                'submitdiv',
357
-                $box_label,
358
-                'post_submit_meta_box',
359
-                $this->_cpt_routes[ $this->_req_action ],
360
-                'side',
361
-                'core'
362
-            );
363
-        }
364
-        // let's add page_templates metabox if this cpt added support for it.
365
-        if ($this->_supports_page_templates($this->_cpt_object->name)) {
366
-            $this->addMetaBox(
367
-                'page_templates',
368
-                esc_html__('Page Template', 'event_espresso'),
369
-                [$this, 'page_template_meta_box'],
370
-                $this->_cpt_routes[ $this->_req_action ],
371
-                'side',
372
-                'default'
373
-            );
374
-        }
375
-        // this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
376
-        if (method_exists($this, 'extra_permalink_field_buttons')) {
377
-            add_filter('get_sample_permalink_html', [$this, 'extra_permalink_field_buttons'], 10, 4);
378
-        }
379
-        // add preview button
380
-        add_filter('get_sample_permalink_html', [$this, 'preview_button_html'], 5, 4);
381
-        // insert our own post_stati dropdown
382
-        add_action('post_submitbox_misc_actions', [$this, 'custom_post_stati_dropdown'], 10);
383
-        // This allows adding additional information to the publish post submitbox on the wp post edit form
384
-        if (method_exists($this, 'extra_misc_actions_publish_box')) {
385
-            add_action('post_submitbox_misc_actions', [$this, 'extra_misc_actions_publish_box'], 10);
386
-        }
387
-        // This allows for adding additional stuff after the title field on the wp post edit form.
388
-        // This is also before the wp_editor for post description field.
389
-        if (method_exists($this, 'edit_form_after_title')) {
390
-            add_action('edit_form_after_title', [$this, 'edit_form_after_title'], 10);
391
-        }
392
-        /**
393
-         * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
394
-         */
395
-        add_filter('clean_url', [$this, 'switch_core_wp_urls_with_ours'], 10, 3);
396
-        parent::_load_page_dependencies();
397
-        // notice we are ALSO going to load the pagenow hook set for this route
398
-        // (see _before_page_setup for the reset of the pagenow global ).
399
-        // This is for any plugins that are doing things properly
400
-        // and hooking into the load page hook for core wp cpt routes.
401
-        global $pagenow;
402
-        add_action('load-' . $pagenow, [$this, 'modify_current_screen'], 20);
403
-        do_action('load-' . $pagenow);
404
-        add_action('admin_enqueue_scripts', [$this, 'setup_autosave_hooks'], 30);
405
-        // we route REALLY early.
406
-        try {
407
-            $this->_route_admin_request();
408
-        } catch (EE_Error $e) {
409
-            $e->get_error();
410
-        }
411
-    }
412
-
413
-
414
-    /**
415
-     * Since we don't want users going to default core wp routes, this will check any wp urls run through the
416
-     * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
417
-     * route instead.
418
-     *
419
-     * @param string $good_protocol_url The escaped url.
420
-     * @param string $original_url      The original url.
421
-     * @param string $_context          The context sent to the esc_url method.
422
-     * @return string possibly a new url for our route.
423
-     */
424
-    public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
425
-    {
426
-        $routes_to_match = [
427
-            0 => [
428
-                'edit.php?post_type=espresso_attendees',
429
-                'admin.php?page=espresso_registrations&action=contact_list',
430
-            ],
431
-            1 => [
432
-                'edit.php?post_type=' . $this->_cpt_object->name,
433
-                'admin.php?page=' . $this->_cpt_object->name,
434
-            ],
435
-        ];
436
-        foreach ($routes_to_match as $route_matches) {
437
-            if (strpos($good_protocol_url, $route_matches[0]) !== false) {
438
-                return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
439
-            }
440
-        }
441
-        return $good_protocol_url;
442
-    }
443
-
444
-
445
-    /**
446
-     * Determine whether the current cpt supports page templates or not.
447
-     *
448
-     * @param string $cpt_name The cpt slug we're checking on.
449
-     * @return bool True supported, false not.
450
-     * @throws InvalidArgumentException
451
-     * @throws InvalidDataTypeException
452
-     * @throws InvalidInterfaceException
453
-     * @since %VER%
454
-     */
455
-    private function _supports_page_templates($cpt_name)
456
-    {
457
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
458
-        $custom_post_types = $this->loader->getShared(
459
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
460
-        );
461
-        $cpt_args          = $custom_post_types->getDefinitions();
462
-        $cpt_args          = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : [];
463
-        $cpt_has_support   = ! empty($cpt_args['page_templates']);
464
-
465
-        // if the installed version of WP is > 4.7 we do some additional checks.
466
-        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
467
-            $post_templates = wp_get_theme()->get_post_templates();
468
-            // if there are $post_templates for this cpt, then we return false for this method because
469
-            // that means we aren't going to load our page template manager and leave that up to the native
470
-            // cpt template manager.
471
-            $cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
472
-        }
473
-
474
-        return $cpt_has_support;
475
-    }
476
-
477
-
478
-    /**
479
-     * Callback for the page_templates metabox selector.
480
-     *
481
-     * @return void
482
-     * @since %VER%
483
-     */
484
-    public function page_template_meta_box()
485
-    {
486
-        global $post;
487
-        $template = '';
488
-
489
-        if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
490
-            $page_template_count = count(get_page_templates());
491
-        } else {
492
-            $page_template_count = count(get_page_templates($post));
493
-        }
494
-
495
-        if ($page_template_count) {
496
-            $page_template = get_post_meta($post->ID, '_wp_page_template', true);
497
-            $template      = ! empty($page_template) ? $page_template : '';
498
-        }
499
-        ?>
282
+		// filter _autosave_containers
283
+		$containers = apply_filters(
284
+			'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
285
+			$this->_autosave_containers,
286
+			$this
287
+		);
288
+		$containers = apply_filters(
289
+			'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
290
+			$containers,
291
+			$this
292
+		);
293
+
294
+		wp_localize_script(
295
+			'event_editor_js',
296
+			'EE_AUTOSAVE_IDS',
297
+			$containers
298
+		); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
299
+
300
+		$unsaved_data_msg = [
301
+			'eventmsg'     => sprintf(
302
+				wp_strip_all_tags(
303
+					__(
304
+						"The changes you made to this %s will be lost if you navigate away from this page.",
305
+						'event_espresso'
306
+					)
307
+				),
308
+				$this->_cpt_object->labels->singular_name
309
+			),
310
+			'inputChanged' => 0,
311
+		];
312
+		wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
313
+	}
314
+
315
+
316
+	/**
317
+	 * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
318
+	 *
319
+	 * @return void
320
+	 * @throws EE_Error
321
+	 * @throws ReflectionException
322
+	 */
323
+	protected function _load_page_dependencies()
324
+	{
325
+		// we only add stuff if this is a cpt_route!
326
+		if (! $this->_cpt_route) {
327
+			parent::_load_page_dependencies();
328
+			return;
329
+		}
330
+		// now let's do some automatic filters into the wp_system
331
+		// and we'll check to make sure the CHILD class
332
+		// automatically has the required methods in place.
333
+		// the following filters are for setting all the redirects
334
+		// on DEFAULT WP custom post type actions
335
+		// let's add a hidden input to the post-edit form
336
+		// so we know when we have to trigger our custom redirects!
337
+		// Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
338
+		add_action('edit_form_after_title', [$this, 'cpt_post_form_hidden_input']);
339
+		// inject our Admin page nav tabs...
340
+		// let's make sure the nav tabs are set if they aren't already
341
+		// if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
342
+		add_action('edit_form_top', [$this, 'inject_nav_tabs']);
343
+		// modify the post_updated messages array
344
+		add_action('post_updated_messages', [$this, 'post_update_messages'], 10);
345
+		// add shortlink button to cpt edit screens.  We can do this as a universal thing BECAUSE,
346
+		// cpts use the same format for shortlinks as posts!
347
+		add_filter('pre_get_shortlink', [$this, 'add_shortlink_button_to_editor'], 10, 4);
348
+		// This basically allows us to change the title of the "publish" metabox area
349
+		// on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
350
+		if (! empty($this->_labels['publishbox'])) {
351
+			$box_label = is_array($this->_labels['publishbox'])
352
+						 && isset($this->_labels['publishbox'][ $this->_req_action ])
353
+				? $this->_labels['publishbox'][ $this->_req_action ]
354
+				: $this->_labels['publishbox'];
355
+			$this->addMetaBox(
356
+				'submitdiv',
357
+				$box_label,
358
+				'post_submit_meta_box',
359
+				$this->_cpt_routes[ $this->_req_action ],
360
+				'side',
361
+				'core'
362
+			);
363
+		}
364
+		// let's add page_templates metabox if this cpt added support for it.
365
+		if ($this->_supports_page_templates($this->_cpt_object->name)) {
366
+			$this->addMetaBox(
367
+				'page_templates',
368
+				esc_html__('Page Template', 'event_espresso'),
369
+				[$this, 'page_template_meta_box'],
370
+				$this->_cpt_routes[ $this->_req_action ],
371
+				'side',
372
+				'default'
373
+			);
374
+		}
375
+		// this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
376
+		if (method_exists($this, 'extra_permalink_field_buttons')) {
377
+			add_filter('get_sample_permalink_html', [$this, 'extra_permalink_field_buttons'], 10, 4);
378
+		}
379
+		// add preview button
380
+		add_filter('get_sample_permalink_html', [$this, 'preview_button_html'], 5, 4);
381
+		// insert our own post_stati dropdown
382
+		add_action('post_submitbox_misc_actions', [$this, 'custom_post_stati_dropdown'], 10);
383
+		// This allows adding additional information to the publish post submitbox on the wp post edit form
384
+		if (method_exists($this, 'extra_misc_actions_publish_box')) {
385
+			add_action('post_submitbox_misc_actions', [$this, 'extra_misc_actions_publish_box'], 10);
386
+		}
387
+		// This allows for adding additional stuff after the title field on the wp post edit form.
388
+		// This is also before the wp_editor for post description field.
389
+		if (method_exists($this, 'edit_form_after_title')) {
390
+			add_action('edit_form_after_title', [$this, 'edit_form_after_title'], 10);
391
+		}
392
+		/**
393
+		 * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
394
+		 */
395
+		add_filter('clean_url', [$this, 'switch_core_wp_urls_with_ours'], 10, 3);
396
+		parent::_load_page_dependencies();
397
+		// notice we are ALSO going to load the pagenow hook set for this route
398
+		// (see _before_page_setup for the reset of the pagenow global ).
399
+		// This is for any plugins that are doing things properly
400
+		// and hooking into the load page hook for core wp cpt routes.
401
+		global $pagenow;
402
+		add_action('load-' . $pagenow, [$this, 'modify_current_screen'], 20);
403
+		do_action('load-' . $pagenow);
404
+		add_action('admin_enqueue_scripts', [$this, 'setup_autosave_hooks'], 30);
405
+		// we route REALLY early.
406
+		try {
407
+			$this->_route_admin_request();
408
+		} catch (EE_Error $e) {
409
+			$e->get_error();
410
+		}
411
+	}
412
+
413
+
414
+	/**
415
+	 * Since we don't want users going to default core wp routes, this will check any wp urls run through the
416
+	 * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
417
+	 * route instead.
418
+	 *
419
+	 * @param string $good_protocol_url The escaped url.
420
+	 * @param string $original_url      The original url.
421
+	 * @param string $_context          The context sent to the esc_url method.
422
+	 * @return string possibly a new url for our route.
423
+	 */
424
+	public function switch_core_wp_urls_with_ours($good_protocol_url, $original_url, $_context)
425
+	{
426
+		$routes_to_match = [
427
+			0 => [
428
+				'edit.php?post_type=espresso_attendees',
429
+				'admin.php?page=espresso_registrations&action=contact_list',
430
+			],
431
+			1 => [
432
+				'edit.php?post_type=' . $this->_cpt_object->name,
433
+				'admin.php?page=' . $this->_cpt_object->name,
434
+			],
435
+		];
436
+		foreach ($routes_to_match as $route_matches) {
437
+			if (strpos($good_protocol_url, $route_matches[0]) !== false) {
438
+				return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
439
+			}
440
+		}
441
+		return $good_protocol_url;
442
+	}
443
+
444
+
445
+	/**
446
+	 * Determine whether the current cpt supports page templates or not.
447
+	 *
448
+	 * @param string $cpt_name The cpt slug we're checking on.
449
+	 * @return bool True supported, false not.
450
+	 * @throws InvalidArgumentException
451
+	 * @throws InvalidDataTypeException
452
+	 * @throws InvalidInterfaceException
453
+	 * @since %VER%
454
+	 */
455
+	private function _supports_page_templates($cpt_name)
456
+	{
457
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
458
+		$custom_post_types = $this->loader->getShared(
459
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
460
+		);
461
+		$cpt_args          = $custom_post_types->getDefinitions();
462
+		$cpt_args          = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : [];
463
+		$cpt_has_support   = ! empty($cpt_args['page_templates']);
464
+
465
+		// if the installed version of WP is > 4.7 we do some additional checks.
466
+		if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
467
+			$post_templates = wp_get_theme()->get_post_templates();
468
+			// if there are $post_templates for this cpt, then we return false for this method because
469
+			// that means we aren't going to load our page template manager and leave that up to the native
470
+			// cpt template manager.
471
+			$cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
472
+		}
473
+
474
+		return $cpt_has_support;
475
+	}
476
+
477
+
478
+	/**
479
+	 * Callback for the page_templates metabox selector.
480
+	 *
481
+	 * @return void
482
+	 * @since %VER%
483
+	 */
484
+	public function page_template_meta_box()
485
+	{
486
+		global $post;
487
+		$template = '';
488
+
489
+		if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
490
+			$page_template_count = count(get_page_templates());
491
+		} else {
492
+			$page_template_count = count(get_page_templates($post));
493
+		}
494
+
495
+		if ($page_template_count) {
496
+			$page_template = get_post_meta($post->ID, '_wp_page_template', true);
497
+			$template      = ! empty($page_template) ? $page_template : '';
498
+		}
499
+		?>
500 500
         <p><strong><?php esc_html_e('Template', 'event_espresso') ?></strong></p>
501 501
         <label class="screen-reader-text" for="page_template"><?php esc_html_e(
502
-            'Page Template',
503
-            'event_espresso'
504
-        ) ?></label>
502
+			'Page Template',
503
+			'event_espresso'
504
+		) ?></label>
505 505
         <select
506 506
             name="page_template" id="page_template"
507 507
         >
@@ -509,474 +509,474 @@  discard block
 block discarded – undo
509 509
             <?php page_template_dropdown($template); ?>
510 510
         </select>
511 511
         <?php
512
-    }
513
-
514
-
515
-    /**
516
-     * if this post is a draft or scheduled post then we provide a preview button for user to click
517
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
518
-     *
519
-     * @param string $return    the current html
520
-     * @param int    $id        the post id for the page
521
-     * @param string $new_title What the title is
522
-     * @param string $new_slug  what the slug is
523
-     * @return string            The new html string for the permalink area
524
-     */
525
-    public function preview_button_html($return, $id, $new_title, $new_slug)
526
-    {
527
-        $post = get_post($id);
528
-        if ('publish' !== get_post_status($post)) {
529
-            $return .= '<span id="view-post-btn"><a target="_blank" href="'
530
-                       . get_preview_post_link($id)
531
-                       . '" class="button button--secondary">'
532
-                       . esc_html__('Preview', 'event_espresso')
533
-                       . '</a></span>'
534
-                       . "\n";
535
-        }
536
-        return $return;
537
-    }
538
-
539
-
540
-    /**
541
-     * add our custom post stati dropdown on the wp post page for this cpt
542
-     *
543
-     * @return void
544
-     */
545
-    public function custom_post_stati_dropdown()
546
-    {
547
-
548
-        $statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
549
-        $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
550
-            ? $statuses[ $this->_cpt_model_obj->status() ]
551
-            : '';
552
-        $template_args    = [
553
-            'cur_status'            => $this->_cpt_model_obj->status(),
554
-            'statuses'              => $statuses,
555
-            'cur_status_label'      => $cur_status_label,
556
-            'localized_status_save' => sprintf(esc_html__('Save %s', 'event_espresso'), $cur_status_label),
557
-        ];
558
-        // we'll add a trash post status (WP doesn't add one for some reason)
559
-        if ($this->_cpt_model_obj->status() === 'trash') {
560
-            $template_args['cur_status_label'] = esc_html__('Trashed', 'event_espresso');
561
-            $statuses['trash']                 = esc_html__('Trashed', 'event_espresso');
562
-            $template_args['statuses']         = $statuses;
563
-        }
564
-
565
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
566
-        EEH_Template::display_template($template, $template_args);
567
-    }
568
-
569
-
570
-    public function setup_autosave_hooks()
571
-    {
572
-        $this->_set_autosave_containers();
573
-        $this->_load_autosave_scripts_styles();
574
-    }
575
-
576
-
577
-    /**
578
-     * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a post object (available
579
-     * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
580
-     * for the nonce in here, but then this method looks for two things:
581
-     * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
582
-     * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
583
-     * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
584
-     * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
585
-     * template args.
586
-     *    1. $template_args['error'] = IF there is an error you can add the message in here.
587
-     *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
588
-     *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
589
-     *    $this->_template_args['data']['items'] = array(
590
-     *        'event-datetime-ids' => '1,2,3';
591
-     *    );
592
-     *    Keep in mind the following things:
593
-     *    - "where" index is for the input with the id as that string.
594
-     *    - "what" index is what will be used for the value of that input.
595
-     *
596
-     * @return void
597
-     * @throws EE_Error
598
-     */
599
-    public function do_extra_autosave_stuff()
600
-    {
601
-        // next let's check for the autosave nonce (we'll use _verify_nonce )
602
-        $nonce = $this->request->getRequestParam('autosavenonce');
603
-        $this->_verify_nonce($nonce, 'autosave');
604
-        // make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
605
-        if (! defined('DOING_AUTOSAVE')) {
606
-            define('DOING_AUTOSAVE', true);
607
-        }
608
-        // if we made it here then the nonce checked out.  Let's run our methods and actions
609
-        $autosave = "_ee_autosave_{$this->_current_view}";
610
-        if (method_exists($this, $autosave)) {
611
-            $this->$autosave();
612
-        } else {
613
-            $this->_template_args['success'] = true;
614
-        }
615
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
616
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
617
-        // now let's return json
618
-        $this->_return_json();
619
-    }
620
-
621
-
622
-    /**
623
-     * This takes care of setting up default routes and pages that utilize the core WP admin pages.
624
-     * Child classes can override the defaults (in cases for adding metaboxes etc.)
625
-     * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
626
-     *
627
-     * @return void
628
-     * @throws EE_Error
629
-     * @throws ReflectionException
630
-     */
631
-    protected function _extend_page_config_for_cpt()
632
-    {
633
-        // before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
634
-        if ($this->raw_req_page !== $this->page_slug) {
635
-            return;
636
-        }
637
-        // set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
638
-        if (! empty($this->_cpt_object)) {
639
-            $this->_page_routes = array_merge(
640
-                [
641
-                    'create_new' => '_create_new_cpt_item',
642
-                    'edit'       => '_edit_cpt_item',
643
-                ],
644
-                $this->_page_routes
645
-            );
646
-            $this->_page_config = array_merge(
647
-                [
648
-                    'create_new' => [
649
-                        'nav'           => [
650
-                            'label' => $this->_cpt_object->labels->add_new_item,
651
-                            'order' => 5,
652
-                        ],
653
-                        'require_nonce' => false,
654
-                    ],
655
-                    'edit'       => [
656
-                        'nav'           => [
657
-                            'label'      => $this->_cpt_object->labels->edit_item,
658
-                            'order'      => 5,
659
-                            'persistent' => false,
660
-                            'url'        => '',
661
-                        ],
662
-                        'require_nonce' => false,
663
-                    ],
664
-                ],
665
-                $this->_page_config
666
-            );
667
-        }
668
-        // load the next section only if this is a matching cpt route as set in the cpt routes array.
669
-        if (! isset($this->_cpt_routes[ $this->_req_action ])) {
670
-            return;
671
-        }
672
-        $this->_cpt_route = true;
673
-        // $this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]);
674
-        // add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
675
-        if (empty($this->_cpt_object)) {
676
-            $msg = sprintf(
677
-                esc_html__(
678
-                    'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
679
-                    'event_espresso'
680
-                ),
681
-                $this->page_slug,
682
-                $this->_req_action,
683
-                get_class($this)
684
-            );
685
-            throw new EE_Error($msg);
686
-        }
687
-        $this->_set_model_object($this->request->getRequestParam('post'));
688
-    }
689
-
690
-
691
-    /**
692
-     * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
693
-     *
694
-     * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
695
-     * @param bool   $ignore_route_check
696
-     * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
697
-     * @throws EE_Error
698
-     * @throws InvalidArgumentException
699
-     * @throws InvalidDataTypeException
700
-     * @throws InvalidInterfaceException
701
-     * @throws ReflectionException
702
-     */
703
-    protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
704
-    {
705
-        $model = null;
706
-        if (
707
-            empty($this->_cpt_model_names)
708
-            || (
709
-                ! $ignore_route_check
710
-                && ! isset($this->_cpt_routes[ $this->_req_action ])
711
-            )
712
-            || (
713
-                $this->_cpt_model_obj instanceof EE_CPT_Base
714
-                && $this->_cpt_model_obj->ID() === $id
715
-            )
716
-        ) {
717
-            // get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
718
-            return;
719
-        }
720
-        // if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
721
-        if ($ignore_route_check) {
722
-            $post_type = get_post_type($id);
723
-            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
724
-            $custom_post_types = $this->loader->getShared(
725
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
726
-            );
727
-            $model_names       = $custom_post_types->getCustomPostTypeModelNames($post_type);
728
-            if (isset($model_names[ $post_type ])) {
729
-                $model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
730
-            }
731
-        } else {
732
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
733
-        }
734
-        if ($model instanceof EEM_Base) {
735
-            $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
736
-        }
737
-        do_action(
738
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
739
-            $this->_cpt_model_obj,
740
-            $req_type
741
-        );
742
-    }
743
-
744
-
745
-    /**
746
-     * admin_init_global
747
-     * This runs all the code that we want executed within the WP admin_init hook.
748
-     * This method executes for ALL EE Admin pages.
749
-     *
750
-     * @return void
751
-     */
752
-    public function admin_init_global()
753
-    {
754
-        $post = $this->request->getRequestParam('post');
755
-        // its possible this is a new save so let's catch that instead
756
-        $post           = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
757
-        $post_type      = $post instanceof WP_Post ? $post->post_type : false;
758
-        $current_route  = isset($this->_req_data['current_route'])
759
-            ? $this->_req_data['current_route']
760
-            : 'shouldneverwork';
761
-        $route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
762
-            ? $this->_cpt_routes[ $current_route ]
763
-            : '';
764
-        add_filter('get_delete_post_link', [$this, 'modify_delete_post_link'], 10, 3);
765
-        add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 3);
766
-        if ($post_type === $route_to_check) {
767
-            add_filter('redirect_post_location', [$this, 'cpt_post_location_redirect'], 10, 2);
768
-        }
769
-        // now let's filter redirect if we're on a revision page and the revision is for an event CPT.
770
-        $revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
771
-        if (! empty($revision)) {
772
-            $action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
773
-            // doing a restore?
774
-            if (! empty($action) && $action === 'restore') {
775
-                // get post for revision
776
-                $rev_post   = get_post($revision);
777
-                $rev_parent = get_post($rev_post->post_parent);
778
-                // only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
779
-                if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
780
-                    add_filter('wp_redirect', [$this, 'revision_redirect'], 10, 2);
781
-                    // restores of revisions
782
-                    add_action('wp_restore_post_revision', [$this, 'restore_revision'], 10, 2);
783
-                }
784
-            }
785
-        }
786
-        // NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
787
-        if ($post_type && $post_type === $route_to_check) {
788
-            // $post_id, $post
789
-            add_action('save_post', [$this, 'insert_update'], 10, 3);
790
-            // $post_id
791
-            add_action('trashed_post', [$this, 'before_trash_cpt_item'], 10);
792
-            add_action('trashed_post', [$this, 'dont_permanently_delete_ee_cpts'], 10);
793
-            add_action('untrashed_post', [$this, 'before_restore_cpt_item'], 10);
794
-            add_action('after_delete_post', [$this, 'before_delete_cpt_item'], 10);
795
-        }
796
-    }
797
-
798
-
799
-    /**
800
-     * Callback for the WordPress trashed_post hook.
801
-     * Execute some basic checks before calling the trash_cpt_item declared in the child class.
802
-     *
803
-     * @param int $post_id
804
-     * @throws EE_Error
805
-     * @throws ReflectionException
806
-     */
807
-    public function before_trash_cpt_item($post_id)
808
-    {
809
-        $this->_set_model_object($post_id, true, 'trash');
810
-        // if our cpt object isn't existent then get out immediately.
811
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
812
-            return;
813
-        }
814
-        $this->trash_cpt_item($post_id);
815
-    }
816
-
817
-
818
-    /**
819
-     * Callback for the WordPress untrashed_post hook.
820
-     * Execute some basic checks before calling the restore_cpt_method in the child class.
821
-     *
822
-     * @param $post_id
823
-     * @throws EE_Error
824
-     * @throws ReflectionException
825
-     */
826
-    public function before_restore_cpt_item($post_id)
827
-    {
828
-        $this->_set_model_object($post_id, true, 'restore');
829
-        // if our cpt object isn't existent then get out immediately.
830
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
831
-            return;
832
-        }
833
-        $this->restore_cpt_item($post_id);
834
-    }
835
-
836
-
837
-    /**
838
-     * Callback for the WordPress after_delete_post hook.
839
-     * Execute some basic checks before calling the delete_cpt_item method in the child class.
840
-     *
841
-     * @param $post_id
842
-     * @throws EE_Error
843
-     * @throws ReflectionException
844
-     */
845
-    public function before_delete_cpt_item($post_id)
846
-    {
847
-        $this->_set_model_object($post_id, true, 'delete');
848
-        // if our cpt object isn't existent then get out immediately.
849
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
850
-            return;
851
-        }
852
-        $this->delete_cpt_item($post_id);
853
-    }
854
-
855
-
856
-    /**
857
-     * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
858
-     * accordingly.
859
-     *
860
-     * @return void
861
-     * @throws EE_Error
862
-     * @throws ReflectionException
863
-     */
864
-    public function verify_cpt_object()
865
-    {
866
-        $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
867
-        // verify event object
868
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
869
-            throw new EE_Error(
870
-                sprintf(
871
-                    esc_html__(
872
-                        'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
873
-                        'event_espresso'
874
-                    ),
875
-                    $label
876
-                )
877
-            );
878
-        }
879
-        // if auto-draft then throw an error
880
-        if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
881
-            EE_Error::overwrite_errors();
882
-            EE_Error::add_error(
883
-                sprintf(
884
-                    esc_html__(
885
-                        'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
886
-                        'event_espresso'
887
-                    ),
888
-                    $label
889
-                ),
890
-                __FILE__,
891
-                __FUNCTION__,
892
-                __LINE__
893
-            );
894
-        }
895
-    }
896
-
897
-
898
-    /**
899
-     * admin_footer_scripts_global
900
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
901
-     * will apply on ALL EE_Admin pages.
902
-     *
903
-     * @return void
904
-     */
905
-    public function admin_footer_scripts_global()
906
-    {
907
-        $this->_add_admin_page_ajax_loading_img();
908
-        $this->_add_admin_page_overlay();
909
-    }
910
-
911
-
912
-    /**
913
-     * add in any global scripts for cpt routes
914
-     *
915
-     * @return void
916
-     * @throws EE_Error
917
-     */
918
-    public function load_global_scripts_styles()
919
-    {
920
-        parent::load_global_scripts_styles();
921
-        if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
922
-            // setup custom post status object for localize script but only if we've got a cpt object
923
-            $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
924
-            if (! empty($statuses)) {
925
-                // get ALL statuses!
926
-                $statuses = $this->_cpt_model_obj->get_all_post_statuses();
927
-                // setup object
928
-                $ee_cpt_statuses = [];
929
-                foreach ($statuses as $status => $label) {
930
-                    $ee_cpt_statuses[ $status ] = [
931
-                        'label'      => $label,
932
-                        'save_label' => sprintf(
933
-                            wp_strip_all_tags(__('Save as %s', 'event_espresso')),
934
-                            $label
935
-                        ),
936
-                    ];
937
-                }
938
-                wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
939
-            }
940
-        }
941
-    }
942
-
943
-
944
-    /**
945
-     * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
946
-     * insert/updates
947
-     *
948
-     * @param int     $post_id ID of post being updated
949
-     * @param WP_Post $post    Post object from WP
950
-     * @param bool    $update  Whether this is an update or a new save.
951
-     * @return void
952
-     * @throws EE_Error
953
-     * @throws ReflectionException
954
-     */
955
-    public function insert_update($post_id, $post, $update)
956
-    {
957
-        // make sure that if this is a revision OR trash action that we don't do any updates!
958
-        if (
959
-            isset($this->_req_data['action'])
960
-            && (
961
-                $this->_req_data['action'] === 'restore'
962
-                || $this->_req_data['action'] === 'trash'
963
-            )
964
-        ) {
965
-            return;
966
-        }
967
-        $this->_set_model_object($post_id, true, 'insert_update');
968
-        // if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
969
-        if (
970
-            $update
971
-            && (
972
-                ! $this->_cpt_model_obj instanceof EE_CPT_Base
973
-                || $this->_cpt_model_obj->ID() !== $post_id
974
-            )
975
-        ) {
976
-            return;
977
-        }
978
-        // check for autosave and update our req_data property accordingly.
979
-        /*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
512
+	}
513
+
514
+
515
+	/**
516
+	 * if this post is a draft or scheduled post then we provide a preview button for user to click
517
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
518
+	 *
519
+	 * @param string $return    the current html
520
+	 * @param int    $id        the post id for the page
521
+	 * @param string $new_title What the title is
522
+	 * @param string $new_slug  what the slug is
523
+	 * @return string            The new html string for the permalink area
524
+	 */
525
+	public function preview_button_html($return, $id, $new_title, $new_slug)
526
+	{
527
+		$post = get_post($id);
528
+		if ('publish' !== get_post_status($post)) {
529
+			$return .= '<span id="view-post-btn"><a target="_blank" href="'
530
+					   . get_preview_post_link($id)
531
+					   . '" class="button button--secondary">'
532
+					   . esc_html__('Preview', 'event_espresso')
533
+					   . '</a></span>'
534
+					   . "\n";
535
+		}
536
+		return $return;
537
+	}
538
+
539
+
540
+	/**
541
+	 * add our custom post stati dropdown on the wp post page for this cpt
542
+	 *
543
+	 * @return void
544
+	 */
545
+	public function custom_post_stati_dropdown()
546
+	{
547
+
548
+		$statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
549
+		$cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
550
+			? $statuses[ $this->_cpt_model_obj->status() ]
551
+			: '';
552
+		$template_args    = [
553
+			'cur_status'            => $this->_cpt_model_obj->status(),
554
+			'statuses'              => $statuses,
555
+			'cur_status_label'      => $cur_status_label,
556
+			'localized_status_save' => sprintf(esc_html__('Save %s', 'event_espresso'), $cur_status_label),
557
+		];
558
+		// we'll add a trash post status (WP doesn't add one for some reason)
559
+		if ($this->_cpt_model_obj->status() === 'trash') {
560
+			$template_args['cur_status_label'] = esc_html__('Trashed', 'event_espresso');
561
+			$statuses['trash']                 = esc_html__('Trashed', 'event_espresso');
562
+			$template_args['statuses']         = $statuses;
563
+		}
564
+
565
+		$template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
566
+		EEH_Template::display_template($template, $template_args);
567
+	}
568
+
569
+
570
+	public function setup_autosave_hooks()
571
+	{
572
+		$this->_set_autosave_containers();
573
+		$this->_load_autosave_scripts_styles();
574
+	}
575
+
576
+
577
+	/**
578
+	 * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a post object (available
579
+	 * in $this->_req_data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
580
+	 * for the nonce in here, but then this method looks for two things:
581
+	 * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
582
+	 * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
583
+	 * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
584
+	 * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
585
+	 * template args.
586
+	 *    1. $template_args['error'] = IF there is an error you can add the message in here.
587
+	 *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
588
+	 *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
589
+	 *    $this->_template_args['data']['items'] = array(
590
+	 *        'event-datetime-ids' => '1,2,3';
591
+	 *    );
592
+	 *    Keep in mind the following things:
593
+	 *    - "where" index is for the input with the id as that string.
594
+	 *    - "what" index is what will be used for the value of that input.
595
+	 *
596
+	 * @return void
597
+	 * @throws EE_Error
598
+	 */
599
+	public function do_extra_autosave_stuff()
600
+	{
601
+		// next let's check for the autosave nonce (we'll use _verify_nonce )
602
+		$nonce = $this->request->getRequestParam('autosavenonce');
603
+		$this->_verify_nonce($nonce, 'autosave');
604
+		// make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
605
+		if (! defined('DOING_AUTOSAVE')) {
606
+			define('DOING_AUTOSAVE', true);
607
+		}
608
+		// if we made it here then the nonce checked out.  Let's run our methods and actions
609
+		$autosave = "_ee_autosave_{$this->_current_view}";
610
+		if (method_exists($this, $autosave)) {
611
+			$this->$autosave();
612
+		} else {
613
+			$this->_template_args['success'] = true;
614
+		}
615
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
616
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
617
+		// now let's return json
618
+		$this->_return_json();
619
+	}
620
+
621
+
622
+	/**
623
+	 * This takes care of setting up default routes and pages that utilize the core WP admin pages.
624
+	 * Child classes can override the defaults (in cases for adding metaboxes etc.)
625
+	 * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
626
+	 *
627
+	 * @return void
628
+	 * @throws EE_Error
629
+	 * @throws ReflectionException
630
+	 */
631
+	protected function _extend_page_config_for_cpt()
632
+	{
633
+		// before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
634
+		if ($this->raw_req_page !== $this->page_slug) {
635
+			return;
636
+		}
637
+		// set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
638
+		if (! empty($this->_cpt_object)) {
639
+			$this->_page_routes = array_merge(
640
+				[
641
+					'create_new' => '_create_new_cpt_item',
642
+					'edit'       => '_edit_cpt_item',
643
+				],
644
+				$this->_page_routes
645
+			);
646
+			$this->_page_config = array_merge(
647
+				[
648
+					'create_new' => [
649
+						'nav'           => [
650
+							'label' => $this->_cpt_object->labels->add_new_item,
651
+							'order' => 5,
652
+						],
653
+						'require_nonce' => false,
654
+					],
655
+					'edit'       => [
656
+						'nav'           => [
657
+							'label'      => $this->_cpt_object->labels->edit_item,
658
+							'order'      => 5,
659
+							'persistent' => false,
660
+							'url'        => '',
661
+						],
662
+						'require_nonce' => false,
663
+					],
664
+				],
665
+				$this->_page_config
666
+			);
667
+		}
668
+		// load the next section only if this is a matching cpt route as set in the cpt routes array.
669
+		if (! isset($this->_cpt_routes[ $this->_req_action ])) {
670
+			return;
671
+		}
672
+		$this->_cpt_route = true;
673
+		// $this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]);
674
+		// add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
675
+		if (empty($this->_cpt_object)) {
676
+			$msg = sprintf(
677
+				esc_html__(
678
+					'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
679
+					'event_espresso'
680
+				),
681
+				$this->page_slug,
682
+				$this->_req_action,
683
+				get_class($this)
684
+			);
685
+			throw new EE_Error($msg);
686
+		}
687
+		$this->_set_model_object($this->request->getRequestParam('post'));
688
+	}
689
+
690
+
691
+	/**
692
+	 * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
693
+	 *
694
+	 * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
695
+	 * @param bool   $ignore_route_check
696
+	 * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
697
+	 * @throws EE_Error
698
+	 * @throws InvalidArgumentException
699
+	 * @throws InvalidDataTypeException
700
+	 * @throws InvalidInterfaceException
701
+	 * @throws ReflectionException
702
+	 */
703
+	protected function _set_model_object($id = null, $ignore_route_check = false, $req_type = '')
704
+	{
705
+		$model = null;
706
+		if (
707
+			empty($this->_cpt_model_names)
708
+			|| (
709
+				! $ignore_route_check
710
+				&& ! isset($this->_cpt_routes[ $this->_req_action ])
711
+			)
712
+			|| (
713
+				$this->_cpt_model_obj instanceof EE_CPT_Base
714
+				&& $this->_cpt_model_obj->ID() === $id
715
+			)
716
+		) {
717
+			// get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
718
+			return;
719
+		}
720
+		// if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
721
+		if ($ignore_route_check) {
722
+			$post_type = get_post_type($id);
723
+			/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
724
+			$custom_post_types = $this->loader->getShared(
725
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
726
+			);
727
+			$model_names       = $custom_post_types->getCustomPostTypeModelNames($post_type);
728
+			if (isset($model_names[ $post_type ])) {
729
+				$model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
730
+			}
731
+		} else {
732
+			$model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
733
+		}
734
+		if ($model instanceof EEM_Base) {
735
+			$this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
736
+		}
737
+		do_action(
738
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
739
+			$this->_cpt_model_obj,
740
+			$req_type
741
+		);
742
+	}
743
+
744
+
745
+	/**
746
+	 * admin_init_global
747
+	 * This runs all the code that we want executed within the WP admin_init hook.
748
+	 * This method executes for ALL EE Admin pages.
749
+	 *
750
+	 * @return void
751
+	 */
752
+	public function admin_init_global()
753
+	{
754
+		$post = $this->request->getRequestParam('post');
755
+		// its possible this is a new save so let's catch that instead
756
+		$post           = isset($this->_req_data['post_ID']) ? get_post($this->_req_data['post_ID']) : $post;
757
+		$post_type      = $post instanceof WP_Post ? $post->post_type : false;
758
+		$current_route  = isset($this->_req_data['current_route'])
759
+			? $this->_req_data['current_route']
760
+			: 'shouldneverwork';
761
+		$route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
762
+			? $this->_cpt_routes[ $current_route ]
763
+			: '';
764
+		add_filter('get_delete_post_link', [$this, 'modify_delete_post_link'], 10, 3);
765
+		add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 3);
766
+		if ($post_type === $route_to_check) {
767
+			add_filter('redirect_post_location', [$this, 'cpt_post_location_redirect'], 10, 2);
768
+		}
769
+		// now let's filter redirect if we're on a revision page and the revision is for an event CPT.
770
+		$revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
771
+		if (! empty($revision)) {
772
+			$action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
773
+			// doing a restore?
774
+			if (! empty($action) && $action === 'restore') {
775
+				// get post for revision
776
+				$rev_post   = get_post($revision);
777
+				$rev_parent = get_post($rev_post->post_parent);
778
+				// only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
779
+				if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
780
+					add_filter('wp_redirect', [$this, 'revision_redirect'], 10, 2);
781
+					// restores of revisions
782
+					add_action('wp_restore_post_revision', [$this, 'restore_revision'], 10, 2);
783
+				}
784
+			}
785
+		}
786
+		// NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
787
+		if ($post_type && $post_type === $route_to_check) {
788
+			// $post_id, $post
789
+			add_action('save_post', [$this, 'insert_update'], 10, 3);
790
+			// $post_id
791
+			add_action('trashed_post', [$this, 'before_trash_cpt_item'], 10);
792
+			add_action('trashed_post', [$this, 'dont_permanently_delete_ee_cpts'], 10);
793
+			add_action('untrashed_post', [$this, 'before_restore_cpt_item'], 10);
794
+			add_action('after_delete_post', [$this, 'before_delete_cpt_item'], 10);
795
+		}
796
+	}
797
+
798
+
799
+	/**
800
+	 * Callback for the WordPress trashed_post hook.
801
+	 * Execute some basic checks before calling the trash_cpt_item declared in the child class.
802
+	 *
803
+	 * @param int $post_id
804
+	 * @throws EE_Error
805
+	 * @throws ReflectionException
806
+	 */
807
+	public function before_trash_cpt_item($post_id)
808
+	{
809
+		$this->_set_model_object($post_id, true, 'trash');
810
+		// if our cpt object isn't existent then get out immediately.
811
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
812
+			return;
813
+		}
814
+		$this->trash_cpt_item($post_id);
815
+	}
816
+
817
+
818
+	/**
819
+	 * Callback for the WordPress untrashed_post hook.
820
+	 * Execute some basic checks before calling the restore_cpt_method in the child class.
821
+	 *
822
+	 * @param $post_id
823
+	 * @throws EE_Error
824
+	 * @throws ReflectionException
825
+	 */
826
+	public function before_restore_cpt_item($post_id)
827
+	{
828
+		$this->_set_model_object($post_id, true, 'restore');
829
+		// if our cpt object isn't existent then get out immediately.
830
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
831
+			return;
832
+		}
833
+		$this->restore_cpt_item($post_id);
834
+	}
835
+
836
+
837
+	/**
838
+	 * Callback for the WordPress after_delete_post hook.
839
+	 * Execute some basic checks before calling the delete_cpt_item method in the child class.
840
+	 *
841
+	 * @param $post_id
842
+	 * @throws EE_Error
843
+	 * @throws ReflectionException
844
+	 */
845
+	public function before_delete_cpt_item($post_id)
846
+	{
847
+		$this->_set_model_object($post_id, true, 'delete');
848
+		// if our cpt object isn't existent then get out immediately.
849
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
850
+			return;
851
+		}
852
+		$this->delete_cpt_item($post_id);
853
+	}
854
+
855
+
856
+	/**
857
+	 * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
858
+	 * accordingly.
859
+	 *
860
+	 * @return void
861
+	 * @throws EE_Error
862
+	 * @throws ReflectionException
863
+	 */
864
+	public function verify_cpt_object()
865
+	{
866
+		$label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
867
+		// verify event object
868
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
869
+			throw new EE_Error(
870
+				sprintf(
871
+					esc_html__(
872
+						'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
873
+						'event_espresso'
874
+					),
875
+					$label
876
+				)
877
+			);
878
+		}
879
+		// if auto-draft then throw an error
880
+		if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
881
+			EE_Error::overwrite_errors();
882
+			EE_Error::add_error(
883
+				sprintf(
884
+					esc_html__(
885
+						'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
886
+						'event_espresso'
887
+					),
888
+					$label
889
+				),
890
+				__FILE__,
891
+				__FUNCTION__,
892
+				__LINE__
893
+			);
894
+		}
895
+	}
896
+
897
+
898
+	/**
899
+	 * admin_footer_scripts_global
900
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
901
+	 * will apply on ALL EE_Admin pages.
902
+	 *
903
+	 * @return void
904
+	 */
905
+	public function admin_footer_scripts_global()
906
+	{
907
+		$this->_add_admin_page_ajax_loading_img();
908
+		$this->_add_admin_page_overlay();
909
+	}
910
+
911
+
912
+	/**
913
+	 * add in any global scripts for cpt routes
914
+	 *
915
+	 * @return void
916
+	 * @throws EE_Error
917
+	 */
918
+	public function load_global_scripts_styles()
919
+	{
920
+		parent::load_global_scripts_styles();
921
+		if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
922
+			// setup custom post status object for localize script but only if we've got a cpt object
923
+			$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
924
+			if (! empty($statuses)) {
925
+				// get ALL statuses!
926
+				$statuses = $this->_cpt_model_obj->get_all_post_statuses();
927
+				// setup object
928
+				$ee_cpt_statuses = [];
929
+				foreach ($statuses as $status => $label) {
930
+					$ee_cpt_statuses[ $status ] = [
931
+						'label'      => $label,
932
+						'save_label' => sprintf(
933
+							wp_strip_all_tags(__('Save as %s', 'event_espresso')),
934
+							$label
935
+						),
936
+					];
937
+				}
938
+				wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
939
+			}
940
+		}
941
+	}
942
+
943
+
944
+	/**
945
+	 * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
946
+	 * insert/updates
947
+	 *
948
+	 * @param int     $post_id ID of post being updated
949
+	 * @param WP_Post $post    Post object from WP
950
+	 * @param bool    $update  Whether this is an update or a new save.
951
+	 * @return void
952
+	 * @throws EE_Error
953
+	 * @throws ReflectionException
954
+	 */
955
+	public function insert_update($post_id, $post, $update)
956
+	{
957
+		// make sure that if this is a revision OR trash action that we don't do any updates!
958
+		if (
959
+			isset($this->_req_data['action'])
960
+			&& (
961
+				$this->_req_data['action'] === 'restore'
962
+				|| $this->_req_data['action'] === 'trash'
963
+			)
964
+		) {
965
+			return;
966
+		}
967
+		$this->_set_model_object($post_id, true, 'insert_update');
968
+		// if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
969
+		if (
970
+			$update
971
+			&& (
972
+				! $this->_cpt_model_obj instanceof EE_CPT_Base
973
+				|| $this->_cpt_model_obj->ID() !== $post_id
974
+			)
975
+		) {
976
+			return;
977
+		}
978
+		// check for autosave and update our req_data property accordingly.
979
+		/*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
980 980
             foreach( (array) $this->_req_data['ee_autosave_data'] as $id => $values ) {
981 981
 
982 982
                 foreach ( (array) $values as $key => $value ) {
@@ -986,541 +986,541 @@  discard block
 block discarded – undo
986 986
 
987 987
         }/**/ // TODO reactivate after autosave is implemented in 4.2
988 988
 
989
-        // take care of updating any selected page_template IF this cpt supports it.
990
-        if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
991
-            // wp version aware.
992
-            if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
993
-                $page_templates = wp_get_theme()->get_page_templates();
994
-            } else {
995
-                $post->page_template = $this->_req_data['page_template'];
996
-                $page_templates      = wp_get_theme()->get_page_templates($post);
997
-            }
998
-            if (
999
-                'default' != $this->_req_data['page_template']
1000
-                && ! isset($page_templates[ $this->_req_data['page_template'] ])
1001
-            ) {
1002
-                EE_Error::add_error(
1003
-                    esc_html__('Invalid Page Template.', 'event_espresso'),
1004
-                    __FILE__,
1005
-                    __FUNCTION__,
1006
-                    __LINE__
1007
-                );
1008
-            } else {
1009
-                update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
1010
-            }
1011
-        }
1012
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
1013
-            return;
1014
-        } //TODO we'll remove this after reimplementing autosave in 4.2
1015
-        $this->_insert_update_cpt_item($post_id, $post);
1016
-    }
1017
-
1018
-
1019
-    /**
1020
-     * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
1021
-     * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
1022
-     * so we don't have to check for our CPT.
1023
-     *
1024
-     * @param int $post_id ID of the post
1025
-     * @return void
1026
-     */
1027
-    public function dont_permanently_delete_ee_cpts($post_id)
1028
-    {
1029
-        // only do this if we're actually processing one of our CPTs
1030
-        // if our cpt object isn't existent then get out immediately.
1031
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1032
-            return;
1033
-        }
1034
-        delete_post_meta($post_id, '_wp_trash_meta_status');
1035
-        delete_post_meta($post_id, '_wp_trash_meta_time');
1036
-        // our cpts may have comments so let's take care of that too
1037
-        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
1038
-    }
1039
-
1040
-
1041
-    /**
1042
-     * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1043
-     * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1044
-     * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1045
-     *
1046
-     * @param int $post_id     ID of cpt item
1047
-     * @param int $revision_id ID of revision being restored
1048
-     * @return void
1049
-     */
1050
-    public function restore_revision($post_id, $revision_id)
1051
-    {
1052
-        $this->_restore_cpt_item($post_id, $revision_id);
1053
-        // global action
1054
-        do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1055
-        // class specific action so you can limit hooking into a specific page.
1056
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1057
-    }
1058
-
1059
-
1060
-    /**
1061
-     * @param int $post_id     ID of cpt item
1062
-     * @param int $revision_id ID of revision for item
1063
-     * @return void
1064
-     * @see restore_revision() for details
1065
-     */
1066
-    abstract protected function _restore_cpt_item($post_id, $revision_id);
1067
-
1068
-
1069
-    /**
1070
-     * Execution of this method is added to the end of the load_page_dependencies method in the parent
1071
-     * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1072
-     * To fix we have to reset the current_screen using the page_slug
1073
-     * (which is identical - or should be - to our registered_post_type id.)
1074
-     * Also, since the core WP file loads the admin_header.php for WP
1075
-     * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1076
-     * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1077
-     *
1078
-     * @return void
1079
-     * @throws EE_Error
1080
-     */
1081
-    public function modify_current_screen()
1082
-    {
1083
-        // ONLY do this if the current page_route IS a cpt route
1084
-        if (! $this->_cpt_route) {
1085
-            return;
1086
-        }
1087
-        // routing things REALLY early b/c this is a cpt admin page
1088
-        set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1089
-        $this->_current_screen       = get_current_screen();
1090
-        $this->_current_screen->base = 'event-espresso';
1091
-        $this->_add_help_tabs(); // we make sure we add any help tabs back in!
1092
-        /*try {
989
+		// take care of updating any selected page_template IF this cpt supports it.
990
+		if ($this->_supports_page_templates($post->post_type) && ! empty($this->_req_data['page_template'])) {
991
+			// wp version aware.
992
+			if (RecommendedVersions::compareWordPressVersion('4.7', '>=')) {
993
+				$page_templates = wp_get_theme()->get_page_templates();
994
+			} else {
995
+				$post->page_template = $this->_req_data['page_template'];
996
+				$page_templates      = wp_get_theme()->get_page_templates($post);
997
+			}
998
+			if (
999
+				'default' != $this->_req_data['page_template']
1000
+				&& ! isset($page_templates[ $this->_req_data['page_template'] ])
1001
+			) {
1002
+				EE_Error::add_error(
1003
+					esc_html__('Invalid Page Template.', 'event_espresso'),
1004
+					__FILE__,
1005
+					__FUNCTION__,
1006
+					__LINE__
1007
+				);
1008
+			} else {
1009
+				update_post_meta($post_id, '_wp_page_template', $this->_req_data['page_template']);
1010
+			}
1011
+		}
1012
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
1013
+			return;
1014
+		} //TODO we'll remove this after reimplementing autosave in 4.2
1015
+		$this->_insert_update_cpt_item($post_id, $post);
1016
+	}
1017
+
1018
+
1019
+	/**
1020
+	 * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
1021
+	 * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
1022
+	 * so we don't have to check for our CPT.
1023
+	 *
1024
+	 * @param int $post_id ID of the post
1025
+	 * @return void
1026
+	 */
1027
+	public function dont_permanently_delete_ee_cpts($post_id)
1028
+	{
1029
+		// only do this if we're actually processing one of our CPTs
1030
+		// if our cpt object isn't existent then get out immediately.
1031
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1032
+			return;
1033
+		}
1034
+		delete_post_meta($post_id, '_wp_trash_meta_status');
1035
+		delete_post_meta($post_id, '_wp_trash_meta_time');
1036
+		// our cpts may have comments so let's take care of that too
1037
+		delete_post_meta($post_id, '_wp_trash_meta_comments_status');
1038
+	}
1039
+
1040
+
1041
+	/**
1042
+	 * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1043
+	 * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1044
+	 * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1045
+	 *
1046
+	 * @param int $post_id     ID of cpt item
1047
+	 * @param int $revision_id ID of revision being restored
1048
+	 * @return void
1049
+	 */
1050
+	public function restore_revision($post_id, $revision_id)
1051
+	{
1052
+		$this->_restore_cpt_item($post_id, $revision_id);
1053
+		// global action
1054
+		do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1055
+		// class specific action so you can limit hooking into a specific page.
1056
+		do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1057
+	}
1058
+
1059
+
1060
+	/**
1061
+	 * @param int $post_id     ID of cpt item
1062
+	 * @param int $revision_id ID of revision for item
1063
+	 * @return void
1064
+	 * @see restore_revision() for details
1065
+	 */
1066
+	abstract protected function _restore_cpt_item($post_id, $revision_id);
1067
+
1068
+
1069
+	/**
1070
+	 * Execution of this method is added to the end of the load_page_dependencies method in the parent
1071
+	 * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1072
+	 * To fix we have to reset the current_screen using the page_slug
1073
+	 * (which is identical - or should be - to our registered_post_type id.)
1074
+	 * Also, since the core WP file loads the admin_header.php for WP
1075
+	 * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1076
+	 * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1077
+	 *
1078
+	 * @return void
1079
+	 * @throws EE_Error
1080
+	 */
1081
+	public function modify_current_screen()
1082
+	{
1083
+		// ONLY do this if the current page_route IS a cpt route
1084
+		if (! $this->_cpt_route) {
1085
+			return;
1086
+		}
1087
+		// routing things REALLY early b/c this is a cpt admin page
1088
+		set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1089
+		$this->_current_screen       = get_current_screen();
1090
+		$this->_current_screen->base = 'event-espresso';
1091
+		$this->_add_help_tabs(); // we make sure we add any help tabs back in!
1092
+		/*try {
1093 1093
             $this->_route_admin_request();
1094 1094
         } catch ( EE_Error $e ) {
1095 1095
             $e->get_error();
1096 1096
         }/**/
1097
-    }
1098
-
1099
-
1100
-    /**
1101
-     * This allows child classes to modify the default editor title that appears when people add a new or edit an
1102
-     * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1103
-     * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1104
-     * default to be.
1105
-     *
1106
-     * @param string $title The new title (or existing if there is no editor_title defined)
1107
-     * @return string
1108
-     */
1109
-    public function add_custom_editor_default_title($title)
1110
-    {
1111
-        return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1112
-            ? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1113
-            : $title;
1114
-    }
1115
-
1116
-
1117
-    /**
1118
-     * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1119
-     *
1120
-     * @param string $shortlink   The already generated shortlink
1121
-     * @param int    $id          Post ID for this item
1122
-     * @param string $context     The context for the link
1123
-     * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1124
-     * @return string
1125
-     */
1126
-    public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1127
-    {
1128
-        if (! empty($id) && get_option('permalink_structure') !== '') {
1129
-            $post = get_post($id);
1130
-            if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1131
-                $shortlink = home_url('?p=' . $post->ID);
1132
-            }
1133
-        }
1134
-        return $shortlink;
1135
-    }
1136
-
1137
-
1138
-    /**
1139
-     * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1140
-     * already run in modify_current_screen())
1141
-     *
1142
-     * @return void
1143
-     * @throws EE_Error
1144
-     * @throws ReflectionException
1145
-     */
1146
-    public function route_admin_request()
1147
-    {
1148
-        if ($this->_cpt_route) {
1149
-            return;
1150
-        }
1151
-        try {
1152
-            $this->_route_admin_request();
1153
-        } catch (EE_Error $e) {
1154
-            $e->get_error();
1155
-        }
1156
-    }
1157
-
1158
-
1159
-    /**
1160
-     * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1161
-     *
1162
-     * @return void
1163
-     */
1164
-    public function cpt_post_form_hidden_input()
1165
-    {
1166
-        // we're also going to add the route value and the current page so we can direct autosave parsing correctly
1167
-        echo '
1097
+	}
1098
+
1099
+
1100
+	/**
1101
+	 * This allows child classes to modify the default editor title that appears when people add a new or edit an
1102
+	 * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1103
+	 * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1104
+	 * default to be.
1105
+	 *
1106
+	 * @param string $title The new title (or existing if there is no editor_title defined)
1107
+	 * @return string
1108
+	 */
1109
+	public function add_custom_editor_default_title($title)
1110
+	{
1111
+		return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1112
+			? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1113
+			: $title;
1114
+	}
1115
+
1116
+
1117
+	/**
1118
+	 * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1119
+	 *
1120
+	 * @param string $shortlink   The already generated shortlink
1121
+	 * @param int    $id          Post ID for this item
1122
+	 * @param string $context     The context for the link
1123
+	 * @param bool   $allow_slugs Whether to allow post slugs in the shortlink.
1124
+	 * @return string
1125
+	 */
1126
+	public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1127
+	{
1128
+		if (! empty($id) && get_option('permalink_structure') !== '') {
1129
+			$post = get_post($id);
1130
+			if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1131
+				$shortlink = home_url('?p=' . $post->ID);
1132
+			}
1133
+		}
1134
+		return $shortlink;
1135
+	}
1136
+
1137
+
1138
+	/**
1139
+	 * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1140
+	 * already run in modify_current_screen())
1141
+	 *
1142
+	 * @return void
1143
+	 * @throws EE_Error
1144
+	 * @throws ReflectionException
1145
+	 */
1146
+	public function route_admin_request()
1147
+	{
1148
+		if ($this->_cpt_route) {
1149
+			return;
1150
+		}
1151
+		try {
1152
+			$this->_route_admin_request();
1153
+		} catch (EE_Error $e) {
1154
+			$e->get_error();
1155
+		}
1156
+	}
1157
+
1158
+
1159
+	/**
1160
+	 * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1161
+	 *
1162
+	 * @return void
1163
+	 */
1164
+	public function cpt_post_form_hidden_input()
1165
+	{
1166
+		// we're also going to add the route value and the current page so we can direct autosave parsing correctly
1167
+		echo '
1168 1168
         <input type="hidden" name="ee_cpt_item_redirect_url" value="' . esc_url_raw($this->_admin_base_url) . '"/>
1169 1169
         <div id="ee-cpt-hidden-inputs">
1170 1170
             <input type="hidden" id="current_route" name="current_route" value="' . esc_attr($this->_current_view) . '"/>
1171 1171
             <input type="hidden" id="current_page" name="current_page" value="' . esc_attr($this->page_slug) . '"/>
1172 1172
         </div>';
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1178
-     *
1179
-     * @param string $location Original location url
1180
-     * @param int    $status   Status for http header
1181
-     * @return string           new (or original) url to redirect to.
1182
-     * @throws EE_Error
1183
-     */
1184
-    public function revision_redirect($location, $status)
1185
-    {
1186
-        // get revision
1187
-        $rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1188
-        // can't do anything without revision so let's get out if not present
1189
-        if (empty($rev_id)) {
1190
-            return $location;
1191
-        }
1192
-        // get rev_post_data
1193
-        $rev        = get_post($rev_id);
1194
-        $admin_url  = $this->_admin_base_url;
1195
-        $query_args = [
1196
-            'action'   => 'edit',
1197
-            'post'     => $rev->post_parent,
1198
-            'revision' => $rev_id,
1199
-            'message'  => 5,
1200
-        ];
1201
-        $this->_process_notices($query_args, true);
1202
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1208
-     *
1209
-     * @param string $link    the original generated link
1210
-     * @param int    $id      post id
1211
-     * @param string $context optional, defaults to display.  How to write the '&'
1212
-     * @return string          the link
1213
-     */
1214
-    public function modify_edit_post_link($link, $id, $context)
1215
-    {
1216
-        $post = get_post($id);
1217
-        if (
1218
-            ! isset($this->_req_data['action'])
1219
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1220
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1221
-        ) {
1222
-            return $link;
1223
-        }
1224
-        $query_args = [
1225
-            'action' => $this->_cpt_edit_routes[ $post->post_type ] ?? 'edit',
1226
-            'post'   => $id,
1227
-        ];
1228
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1234
-     * our routes.
1235
-     *
1236
-     * @param string $delete_link  original delete link
1237
-     * @param int    $post_id      id of cpt object
1238
-     * @param bool   $force_delete whether this is forcing a hard delete instead of trash
1239
-     * @return string new delete link
1240
-     * @throws EE_Error
1241
-     * @throws ReflectionException
1242
-     */
1243
-    public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1244
-    {
1245
-        $post = get_post($post_id);
1246
-
1247
-        if (
1248
-            empty($this->_req_data['action'])
1249
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1250
-            || ! $post instanceof WP_Post
1251
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1252
-        ) {
1253
-            return $delete_link;
1254
-        }
1255
-        $this->_set_model_object($post->ID, true);
1256
-
1257
-        // returns something like `trash_event` or `trash_attendee` or `trash_venue`
1258
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1259
-
1260
-        return EE_Admin_Page::add_query_args_and_nonce(
1261
-            [
1262
-                'page'   => $this->_req_data['page'],
1263
-                'action' => $action,
1264
-                $this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1265
-                         => $post->ID,
1266
-            ],
1267
-            admin_url()
1268
-        );
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1274
-     * so that we can hijack the default redirect locations for wp custom post types
1275
-     * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1276
-     *
1277
-     * @param string $location This is the incoming currently set redirect location
1278
-     * @param string $post_id  This is the 'ID' value of the wp_posts table
1279
-     * @return string           the new location to redirect to
1280
-     * @throws EE_Error
1281
-     */
1282
-    public function cpt_post_location_redirect($location, $post_id)
1283
-    {
1284
-        // we DO have a match so let's setup the url
1285
-        // we have to get the post to determine our route
1286
-        $post       = get_post($post_id);
1287
-        $edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1288
-        // shared query_args
1289
-        $query_args = ['action' => $edit_route, 'post' => $post_id];
1290
-        $admin_url  = $this->_admin_base_url;
1291
-        if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1292
-            $status = get_post_status($post_id);
1293
-            if (isset($this->_req_data['publish'])) {
1294
-                switch ($status) {
1295
-                    case 'pending':
1296
-                        $message = 8;
1297
-                        break;
1298
-                    case 'future':
1299
-                        $message = 9;
1300
-                        break;
1301
-                    default:
1302
-                        $message = 6;
1303
-                }
1304
-            } else {
1305
-                $message = 'draft' === $status ? 10 : 1;
1306
-            }
1307
-        } elseif (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1308
-            $message = 2;
1309
-        } elseif (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1310
-            $message = 3;
1311
-        } elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1312
-            $message = 7;
1313
-        } else {
1314
-            $message = 4;
1315
-        }
1316
-        // change the message if the post type is not viewable on the frontend
1317
-        $this->_cpt_object = get_post_type_object($post->post_type);
1318
-        $message           = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1319
-        $query_args        = array_merge(['message' => $message], $query_args);
1320
-        $this->_process_notices($query_args, true);
1321
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * This method is called to inject nav tabs on core WP cpt pages
1327
-     *
1328
-     * @return void
1329
-     * @throws EE_Error
1330
-     */
1331
-    public function inject_nav_tabs()
1332
-    {
1333
-        echo wp_kses($this->_get_main_nav_tabs(), AllowedTags::getWithFormTags());
1334
-    }
1335
-
1336
-
1337
-    /**
1338
-     * This just sets up the post update messages when an update form is loaded
1339
-     *
1340
-     * @param array $messages the original messages array
1341
-     * @return array           the new messages array
1342
-     */
1343
-    public function post_update_messages($messages)
1344
-    {
1345
-        global $post;
1346
-        $id       = $this->request->getRequestParam('post');
1347
-        $id       = empty($id) && is_object($post) ? $post->ID : null;
1348
-        $revision = $this->request->getRequestParam('revision', 0, 'int');
1349
-
1350
-        $messages[ $post->post_type ] = [
1351
-            0  => '', // Unused. Messages start at index 1.
1352
-            1  => sprintf(
1353
-                esc_html__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1354
-                $this->_cpt_object->labels->singular_name,
1355
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1356
-                '</a>'
1357
-            ),
1358
-            2  => esc_html__('Custom field updated', 'event_espresso'),
1359
-            3  => esc_html__('Custom field deleted.', 'event_espresso'),
1360
-            4  => sprintf(esc_html__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1361
-            5  => $revision
1362
-                ? sprintf(
1363
-                    esc_html__('%s restored to revision from %s', 'event_espresso'),
1364
-                    $this->_cpt_object->labels->singular_name,
1365
-                    wp_post_revision_title($revision, false)
1366
-                )
1367
-                : false,
1368
-            6  => sprintf(
1369
-                esc_html__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1370
-                $this->_cpt_object->labels->singular_name,
1371
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1372
-                '</a>'
1373
-            ),
1374
-            7  => sprintf(esc_html__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1375
-            8  => sprintf(
1376
-                esc_html__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1377
-                $this->_cpt_object->labels->singular_name,
1378
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1379
-                '</a>'
1380
-            ),
1381
-            9  => sprintf(
1382
-                esc_html__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1383
-                $this->_cpt_object->labels->singular_name,
1384
-                '<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1385
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1386
-                '</a>'
1387
-            ),
1388
-            10 => sprintf(
1389
-                esc_html__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1390
-                $this->_cpt_object->labels->singular_name,
1391
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1392
-                '</a>'
1393
-            ),
1394
-        ];
1395
-        return $messages;
1396
-    }
1397
-
1398
-
1399
-    /**
1400
-     * default method for the 'create_new' route for cpt admin pages.
1401
-     * For reference what to include in here, see wp-admin/post-new.php
1402
-     *
1403
-     * @return void
1404
-     */
1405
-    protected function _create_new_cpt_item()
1406
-    {
1407
-        // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1408
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1409
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1410
-        $post_type_object = $this->_cpt_object;
1411
-        $title            = $post_type_object->labels->add_new_item;
1412
-        $post             = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1413
-        add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1414
-        // modify the default editor title field with default title.
1415
-        add_filter('enter_title_here', [$this, 'add_custom_editor_default_title'], 10);
1416
-        $this->loadEditorTemplate(true);
1417
-    }
1418
-
1419
-
1420
-    /**
1421
-     * Enqueues auto-save and loads the editor template
1422
-     *
1423
-     * @param bool $creating
1424
-     */
1425
-    private function loadEditorTemplate($creating = true)
1426
-    {
1427
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1428
-        // these vars are used by the template
1429
-        $editing = true;
1430
-        $post_ID = $post->ID;
1431
-        if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1432
-            // only enqueue autosave when creating event (necessary to get permalink/url generated)
1433
-            // otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1434
-            if ($creating) {
1435
-                wp_enqueue_script('autosave');
1436
-            } elseif (
1437
-                isset($this->_cpt_routes[ $this->_req_data['action'] ])
1438
-                && ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1439
-            ) {
1440
-                $create_new_action = apply_filters(
1441
-                    'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1442
-                    'create_new',
1443
-                    $this
1444
-                );
1445
-                $post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1446
-                    array(
1447
-                        'action' => $create_new_action,
1448
-                        'page'   => $this->page_slug,
1449
-                    ),
1450
-                    'admin.php'
1451
-                );
1452
-            }
1453
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1454
-        }
1455
-    }
1456
-
1457
-
1458
-    public function add_new_admin_page_global()
1459
-    {
1460
-        $admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1461
-        ?>
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1178
+	 *
1179
+	 * @param string $location Original location url
1180
+	 * @param int    $status   Status for http header
1181
+	 * @return string           new (or original) url to redirect to.
1182
+	 * @throws EE_Error
1183
+	 */
1184
+	public function revision_redirect($location, $status)
1185
+	{
1186
+		// get revision
1187
+		$rev_id = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
1188
+		// can't do anything without revision so let's get out if not present
1189
+		if (empty($rev_id)) {
1190
+			return $location;
1191
+		}
1192
+		// get rev_post_data
1193
+		$rev        = get_post($rev_id);
1194
+		$admin_url  = $this->_admin_base_url;
1195
+		$query_args = [
1196
+			'action'   => 'edit',
1197
+			'post'     => $rev->post_parent,
1198
+			'revision' => $rev_id,
1199
+			'message'  => 5,
1200
+		];
1201
+		$this->_process_notices($query_args, true);
1202
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1208
+	 *
1209
+	 * @param string $link    the original generated link
1210
+	 * @param int    $id      post id
1211
+	 * @param string $context optional, defaults to display.  How to write the '&'
1212
+	 * @return string          the link
1213
+	 */
1214
+	public function modify_edit_post_link($link, $id, $context)
1215
+	{
1216
+		$post = get_post($id);
1217
+		if (
1218
+			! isset($this->_req_data['action'])
1219
+			|| ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1220
+			|| $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1221
+		) {
1222
+			return $link;
1223
+		}
1224
+		$query_args = [
1225
+			'action' => $this->_cpt_edit_routes[ $post->post_type ] ?? 'edit',
1226
+			'post'   => $id,
1227
+		];
1228
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1234
+	 * our routes.
1235
+	 *
1236
+	 * @param string $delete_link  original delete link
1237
+	 * @param int    $post_id      id of cpt object
1238
+	 * @param bool   $force_delete whether this is forcing a hard delete instead of trash
1239
+	 * @return string new delete link
1240
+	 * @throws EE_Error
1241
+	 * @throws ReflectionException
1242
+	 */
1243
+	public function modify_delete_post_link($delete_link, $post_id, $force_delete)
1244
+	{
1245
+		$post = get_post($post_id);
1246
+
1247
+		if (
1248
+			empty($this->_req_data['action'])
1249
+			|| ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1250
+			|| ! $post instanceof WP_Post
1251
+			|| $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1252
+		) {
1253
+			return $delete_link;
1254
+		}
1255
+		$this->_set_model_object($post->ID, true);
1256
+
1257
+		// returns something like `trash_event` or `trash_attendee` or `trash_venue`
1258
+		$action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1259
+
1260
+		return EE_Admin_Page::add_query_args_and_nonce(
1261
+			[
1262
+				'page'   => $this->_req_data['page'],
1263
+				'action' => $action,
1264
+				$this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name()
1265
+						 => $post->ID,
1266
+			],
1267
+			admin_url()
1268
+		);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1274
+	 * so that we can hijack the default redirect locations for wp custom post types
1275
+	 * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1276
+	 *
1277
+	 * @param string $location This is the incoming currently set redirect location
1278
+	 * @param string $post_id  This is the 'ID' value of the wp_posts table
1279
+	 * @return string           the new location to redirect to
1280
+	 * @throws EE_Error
1281
+	 */
1282
+	public function cpt_post_location_redirect($location, $post_id)
1283
+	{
1284
+		// we DO have a match so let's setup the url
1285
+		// we have to get the post to determine our route
1286
+		$post       = get_post($post_id);
1287
+		$edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1288
+		// shared query_args
1289
+		$query_args = ['action' => $edit_route, 'post' => $post_id];
1290
+		$admin_url  = $this->_admin_base_url;
1291
+		if (isset($this->_req_data['save']) || isset($this->_req_data['publish'])) {
1292
+			$status = get_post_status($post_id);
1293
+			if (isset($this->_req_data['publish'])) {
1294
+				switch ($status) {
1295
+					case 'pending':
1296
+						$message = 8;
1297
+						break;
1298
+					case 'future':
1299
+						$message = 9;
1300
+						break;
1301
+					default:
1302
+						$message = 6;
1303
+				}
1304
+			} else {
1305
+				$message = 'draft' === $status ? 10 : 1;
1306
+			}
1307
+		} elseif (isset($this->_req_data['addmeta']) && $this->_req_data['addmeta']) {
1308
+			$message = 2;
1309
+		} elseif (isset($this->_req_data['deletemeta']) && $this->_req_data['deletemeta']) {
1310
+			$message = 3;
1311
+		} elseif ($this->_req_data['action'] === 'post-quickpress-save-cont') {
1312
+			$message = 7;
1313
+		} else {
1314
+			$message = 4;
1315
+		}
1316
+		// change the message if the post type is not viewable on the frontend
1317
+		$this->_cpt_object = get_post_type_object($post->post_type);
1318
+		$message           = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1319
+		$query_args        = array_merge(['message' => $message], $query_args);
1320
+		$this->_process_notices($query_args, true);
1321
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * This method is called to inject nav tabs on core WP cpt pages
1327
+	 *
1328
+	 * @return void
1329
+	 * @throws EE_Error
1330
+	 */
1331
+	public function inject_nav_tabs()
1332
+	{
1333
+		echo wp_kses($this->_get_main_nav_tabs(), AllowedTags::getWithFormTags());
1334
+	}
1335
+
1336
+
1337
+	/**
1338
+	 * This just sets up the post update messages when an update form is loaded
1339
+	 *
1340
+	 * @param array $messages the original messages array
1341
+	 * @return array           the new messages array
1342
+	 */
1343
+	public function post_update_messages($messages)
1344
+	{
1345
+		global $post;
1346
+		$id       = $this->request->getRequestParam('post');
1347
+		$id       = empty($id) && is_object($post) ? $post->ID : null;
1348
+		$revision = $this->request->getRequestParam('revision', 0, 'int');
1349
+
1350
+		$messages[ $post->post_type ] = [
1351
+			0  => '', // Unused. Messages start at index 1.
1352
+			1  => sprintf(
1353
+				esc_html__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1354
+				$this->_cpt_object->labels->singular_name,
1355
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1356
+				'</a>'
1357
+			),
1358
+			2  => esc_html__('Custom field updated', 'event_espresso'),
1359
+			3  => esc_html__('Custom field deleted.', 'event_espresso'),
1360
+			4  => sprintf(esc_html__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1361
+			5  => $revision
1362
+				? sprintf(
1363
+					esc_html__('%s restored to revision from %s', 'event_espresso'),
1364
+					$this->_cpt_object->labels->singular_name,
1365
+					wp_post_revision_title($revision, false)
1366
+				)
1367
+				: false,
1368
+			6  => sprintf(
1369
+				esc_html__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1370
+				$this->_cpt_object->labels->singular_name,
1371
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1372
+				'</a>'
1373
+			),
1374
+			7  => sprintf(esc_html__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1375
+			8  => sprintf(
1376
+				esc_html__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1377
+				$this->_cpt_object->labels->singular_name,
1378
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1379
+				'</a>'
1380
+			),
1381
+			9  => sprintf(
1382
+				esc_html__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1383
+				$this->_cpt_object->labels->singular_name,
1384
+				'<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1385
+				'<a target="_blank" href="' . esc_url(get_permalink($id)),
1386
+				'</a>'
1387
+			),
1388
+			10 => sprintf(
1389
+				esc_html__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1390
+				$this->_cpt_object->labels->singular_name,
1391
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1392
+				'</a>'
1393
+			),
1394
+		];
1395
+		return $messages;
1396
+	}
1397
+
1398
+
1399
+	/**
1400
+	 * default method for the 'create_new' route for cpt admin pages.
1401
+	 * For reference what to include in here, see wp-admin/post-new.php
1402
+	 *
1403
+	 * @return void
1404
+	 */
1405
+	protected function _create_new_cpt_item()
1406
+	{
1407
+		// gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1408
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1409
+		$post_type        = $this->_cpt_routes[ $this->_req_action ];
1410
+		$post_type_object = $this->_cpt_object;
1411
+		$title            = $post_type_object->labels->add_new_item;
1412
+		$post             = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1413
+		add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1414
+		// modify the default editor title field with default title.
1415
+		add_filter('enter_title_here', [$this, 'add_custom_editor_default_title'], 10);
1416
+		$this->loadEditorTemplate(true);
1417
+	}
1418
+
1419
+
1420
+	/**
1421
+	 * Enqueues auto-save and loads the editor template
1422
+	 *
1423
+	 * @param bool $creating
1424
+	 */
1425
+	private function loadEditorTemplate($creating = true)
1426
+	{
1427
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1428
+		// these vars are used by the template
1429
+		$editing = true;
1430
+		$post_ID = $post->ID;
1431
+		if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1432
+			// only enqueue autosave when creating event (necessary to get permalink/url generated)
1433
+			// otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1434
+			if ($creating) {
1435
+				wp_enqueue_script('autosave');
1436
+			} elseif (
1437
+				isset($this->_cpt_routes[ $this->_req_data['action'] ])
1438
+				&& ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1439
+			) {
1440
+				$create_new_action = apply_filters(
1441
+					'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1442
+					'create_new',
1443
+					$this
1444
+				);
1445
+				$post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1446
+					array(
1447
+						'action' => $create_new_action,
1448
+						'page'   => $this->page_slug,
1449
+					),
1450
+					'admin.php'
1451
+				);
1452
+			}
1453
+			include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1454
+		}
1455
+	}
1456
+
1457
+
1458
+	public function add_new_admin_page_global()
1459
+	{
1460
+		$admin_page = ! empty($this->_req_data['post']) ? 'post-php' : 'post-new-php';
1461
+		?>
1462 1462
         <script type="text/javascript">
1463 1463
             adminpage = '<?php echo esc_js($admin_page); ?>';
1464 1464
         </script>
1465 1465
         <?php
1466
-    }
1467
-
1468
-
1469
-    /**
1470
-     * default method for the 'edit' route for cpt admin pages
1471
-     * For reference on what to put in here, refer to wp-admin/post.php
1472
-     *
1473
-     * @return string   template for edit cpt form
1474
-     */
1475
-    protected function _edit_cpt_item()
1476
-    {
1477
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1478
-        $post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1479
-        $post    = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1480
-        if (empty($post)) {
1481
-            wp_die(esc_html__(
1482
-                'You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?',
1483
-                'event_espresso'
1484
-            ));
1485
-        }
1486
-
1487
-        $post_lock = $this->request->getRequestParam('get-post-lock');
1488
-        if ($post_lock) {
1489
-            wp_set_post_lock($post_id);
1490
-            wp_redirect(get_edit_post_link($post_id, 'url'));
1491
-            exit();
1492
-        }
1493
-
1494
-        // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1495
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1496
-        $post_type_object = $this->_cpt_object;
1497
-
1498
-        if (! wp_check_post_lock($post->ID)) {
1499
-            wp_set_post_lock($post->ID);
1500
-        }
1501
-        add_action('admin_footer', '_admin_notice_post_locked');
1502
-        if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1503
-            wp_enqueue_script('admin-comments');
1504
-            enqueue_comment_hotkeys_js();
1505
-        }
1506
-        add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1507
-        // modify the default editor title field with default title.
1508
-        add_filter('enter_title_here', [$this, 'add_custom_editor_default_title'], 10);
1509
-        $this->loadEditorTemplate(false);
1510
-    }
1511
-
1512
-
1513
-
1514
-    /**
1515
-     * some getters
1516
-     */
1517
-    /**
1518
-     * This returns the protected _cpt_model_obj property
1519
-     *
1520
-     * @return EE_CPT_Base
1521
-     */
1522
-    public function get_cpt_model_obj()
1523
-    {
1524
-        return $this->_cpt_model_obj;
1525
-    }
1466
+	}
1467
+
1468
+
1469
+	/**
1470
+	 * default method for the 'edit' route for cpt admin pages
1471
+	 * For reference on what to put in here, refer to wp-admin/post.php
1472
+	 *
1473
+	 * @return string   template for edit cpt form
1474
+	 */
1475
+	protected function _edit_cpt_item()
1476
+	{
1477
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1478
+		$post_id = isset($this->_req_data['post']) ? $this->_req_data['post'] : null;
1479
+		$post    = ! empty($post_id) ? get_post($post_id, OBJECT, 'edit') : null;
1480
+		if (empty($post)) {
1481
+			wp_die(esc_html__(
1482
+				'You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?',
1483
+				'event_espresso'
1484
+			));
1485
+		}
1486
+
1487
+		$post_lock = $this->request->getRequestParam('get-post-lock');
1488
+		if ($post_lock) {
1489
+			wp_set_post_lock($post_id);
1490
+			wp_redirect(get_edit_post_link($post_id, 'url'));
1491
+			exit();
1492
+		}
1493
+
1494
+		// template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1495
+		$post_type        = $this->_cpt_routes[ $this->_req_action ];
1496
+		$post_type_object = $this->_cpt_object;
1497
+
1498
+		if (! wp_check_post_lock($post->ID)) {
1499
+			wp_set_post_lock($post->ID);
1500
+		}
1501
+		add_action('admin_footer', '_admin_notice_post_locked');
1502
+		if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1503
+			wp_enqueue_script('admin-comments');
1504
+			enqueue_comment_hotkeys_js();
1505
+		}
1506
+		add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1507
+		// modify the default editor title field with default title.
1508
+		add_filter('enter_title_here', [$this, 'add_custom_editor_default_title'], 10);
1509
+		$this->loadEditorTemplate(false);
1510
+	}
1511
+
1512
+
1513
+
1514
+	/**
1515
+	 * some getters
1516
+	 */
1517
+	/**
1518
+	 * This returns the protected _cpt_model_obj property
1519
+	 *
1520
+	 * @return EE_CPT_Base
1521
+	 */
1522
+	public function get_cpt_model_obj()
1523
+	{
1524
+		return $this->_cpt_model_obj;
1525
+	}
1526 1526
 }
Please login to merge, or discard this patch.
Spacing   +74 added lines, -74 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
      */
160 160
     protected function getLoader()
161 161
     {
162
-        if (! $this->loader instanceof LoaderInterface) {
162
+        if ( ! $this->loader instanceof LoaderInterface) {
163 163
             $this->loader = LoaderFactory::getLoader();
164 164
         }
165 165
         return $this->loader;
@@ -183,15 +183,15 @@  discard block
 block discarded – undo
183 183
             ],
184 184
             $this->_cpt_routes
185 185
         );
186
-        $cpt_route_action  = isset($this->_cpt_routes[ $this->raw_req_action ])
187
-            ? $this->_cpt_routes[ $this->raw_req_action ]
186
+        $cpt_route_action = isset($this->_cpt_routes[$this->raw_req_action])
187
+            ? $this->_cpt_routes[$this->raw_req_action]
188 188
             : null;
189 189
         // let's see if the current route has a value for cpt_object_slug. if it does, we use that instead of the page
190 190
         $page              = $this->raw_req_page ?: $this->page_slug;
191 191
         $page              = $cpt_route_action ?: $page;
192 192
         $this->_cpt_object = get_post_type_object($page);
193 193
         // tweak pagenow for page loading.
194
-        if (! $this->_pagenow_map) {
194
+        if ( ! $this->_pagenow_map) {
195 195
             $this->_pagenow_map = [
196 196
                 'create_new' => 'post-new.php',
197 197
                 'edit'       => 'post.php',
@@ -217,10 +217,10 @@  discard block
 block discarded – undo
217 217
         // possibly reset pagenow.
218 218
         if (
219 219
             $this->page_slug === $this->raw_req_page
220
-            && isset($this->_pagenow_map[ $this->raw_req_action ])
220
+            && isset($this->_pagenow_map[$this->raw_req_action])
221 221
         ) {
222 222
             global $pagenow, $hook_suffix;
223
-            $pagenow     = $this->_pagenow_map[ $this->raw_req_action ];
223
+            $pagenow     = $this->_pagenow_map[$this->raw_req_action];
224 224
             $hook_suffix = $pagenow;
225 225
         }
226 226
     }
@@ -252,7 +252,7 @@  discard block
 block discarded – undo
252 252
         if (empty($wp_meta_boxes)) {
253 253
             return;
254 254
         }
255
-        $current_metaboxes = isset($wp_meta_boxes[ $this->page_slug ]) ? $wp_meta_boxes[ $this->page_slug ] : [];
255
+        $current_metaboxes = isset($wp_meta_boxes[$this->page_slug]) ? $wp_meta_boxes[$this->page_slug] : [];
256 256
         foreach ($current_metaboxes as $box_context) {
257 257
             foreach ($box_context as $box_details) {
258 258
                 foreach ($box_details as $box) {
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
             $this
287 287
         );
288 288
         $containers = apply_filters(
289
-            'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
289
+            'FHEE__EE_Admin_Page_CPT__'.get_class($this).'___load_autosave_scripts_styles__containers',
290 290
             $containers,
291 291
             $this
292 292
         );
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
     protected function _load_page_dependencies()
324 324
     {
325 325
         // we only add stuff if this is a cpt_route!
326
-        if (! $this->_cpt_route) {
326
+        if ( ! $this->_cpt_route) {
327 327
             parent::_load_page_dependencies();
328 328
             return;
329 329
         }
@@ -347,16 +347,16 @@  discard block
 block discarded – undo
347 347
         add_filter('pre_get_shortlink', [$this, 'add_shortlink_button_to_editor'], 10, 4);
348 348
         // This basically allows us to change the title of the "publish" metabox area
349 349
         // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
350
-        if (! empty($this->_labels['publishbox'])) {
350
+        if ( ! empty($this->_labels['publishbox'])) {
351 351
             $box_label = is_array($this->_labels['publishbox'])
352
-                         && isset($this->_labels['publishbox'][ $this->_req_action ])
353
-                ? $this->_labels['publishbox'][ $this->_req_action ]
352
+                         && isset($this->_labels['publishbox'][$this->_req_action])
353
+                ? $this->_labels['publishbox'][$this->_req_action]
354 354
                 : $this->_labels['publishbox'];
355 355
             $this->addMetaBox(
356 356
                 'submitdiv',
357 357
                 $box_label,
358 358
                 'post_submit_meta_box',
359
-                $this->_cpt_routes[ $this->_req_action ],
359
+                $this->_cpt_routes[$this->_req_action],
360 360
                 'side',
361 361
                 'core'
362 362
             );
@@ -367,7 +367,7 @@  discard block
 block discarded – undo
367 367
                 'page_templates',
368 368
                 esc_html__('Page Template', 'event_espresso'),
369 369
                 [$this, 'page_template_meta_box'],
370
-                $this->_cpt_routes[ $this->_req_action ],
370
+                $this->_cpt_routes[$this->_req_action],
371 371
                 'side',
372 372
                 'default'
373 373
             );
@@ -399,8 +399,8 @@  discard block
 block discarded – undo
399 399
         // This is for any plugins that are doing things properly
400 400
         // and hooking into the load page hook for core wp cpt routes.
401 401
         global $pagenow;
402
-        add_action('load-' . $pagenow, [$this, 'modify_current_screen'], 20);
403
-        do_action('load-' . $pagenow);
402
+        add_action('load-'.$pagenow, [$this, 'modify_current_screen'], 20);
403
+        do_action('load-'.$pagenow);
404 404
         add_action('admin_enqueue_scripts', [$this, 'setup_autosave_hooks'], 30);
405 405
         // we route REALLY early.
406 406
         try {
@@ -429,8 +429,8 @@  discard block
 block discarded – undo
429 429
                 'admin.php?page=espresso_registrations&action=contact_list',
430 430
             ],
431 431
             1 => [
432
-                'edit.php?post_type=' . $this->_cpt_object->name,
433
-                'admin.php?page=' . $this->_cpt_object->name,
432
+                'edit.php?post_type='.$this->_cpt_object->name,
433
+                'admin.php?page='.$this->_cpt_object->name,
434 434
             ],
435 435
         ];
436 436
         foreach ($routes_to_match as $route_matches) {
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
             'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
460 460
         );
461 461
         $cpt_args          = $custom_post_types->getDefinitions();
462
-        $cpt_args          = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : [];
462
+        $cpt_args          = isset($cpt_args[$cpt_name]) ? $cpt_args[$cpt_name]['args'] : [];
463 463
         $cpt_has_support   = ! empty($cpt_args['page_templates']);
464 464
 
465 465
         // if the installed version of WP is > 4.7 we do some additional checks.
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
             // if there are $post_templates for this cpt, then we return false for this method because
469 469
             // that means we aren't going to load our page template manager and leave that up to the native
470 470
             // cpt template manager.
471
-            $cpt_has_support = ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
471
+            $cpt_has_support = ! isset($post_templates[$cpt_name]) ? $cpt_has_support : false;
472 472
         }
473 473
 
474 474
         return $cpt_has_support;
@@ -547,7 +547,7 @@  discard block
 block discarded – undo
547 547
 
548 548
         $statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
549 549
         $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
550
-            ? $statuses[ $this->_cpt_model_obj->status() ]
550
+            ? $statuses[$this->_cpt_model_obj->status()]
551 551
             : '';
552 552
         $template_args    = [
553 553
             'cur_status'            => $this->_cpt_model_obj->status(),
@@ -562,7 +562,7 @@  discard block
 block discarded – undo
562 562
             $template_args['statuses']         = $statuses;
563 563
         }
564 564
 
565
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
565
+        $template = EE_ADMIN_TEMPLATE.'status_dropdown.template.php';
566 566
         EEH_Template::display_template($template, $template_args);
567 567
     }
568 568
 
@@ -602,7 +602,7 @@  discard block
 block discarded – undo
602 602
         $nonce = $this->request->getRequestParam('autosavenonce');
603 603
         $this->_verify_nonce($nonce, 'autosave');
604 604
         // make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
605
-        if (! defined('DOING_AUTOSAVE')) {
605
+        if ( ! defined('DOING_AUTOSAVE')) {
606 606
             define('DOING_AUTOSAVE', true);
607 607
         }
608 608
         // if we made it here then the nonce checked out.  Let's run our methods and actions
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
             $this->_template_args['success'] = true;
614 614
         }
615 615
         do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
616
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
616
+        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_'.get_class($this), $this);
617 617
         // now let's return json
618 618
         $this->_return_json();
619 619
     }
@@ -635,7 +635,7 @@  discard block
 block discarded – undo
635 635
             return;
636 636
         }
637 637
         // set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
638
-        if (! empty($this->_cpt_object)) {
638
+        if ( ! empty($this->_cpt_object)) {
639 639
             $this->_page_routes = array_merge(
640 640
                 [
641 641
                     'create_new' => '_create_new_cpt_item',
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
             );
667 667
         }
668 668
         // load the next section only if this is a matching cpt route as set in the cpt routes array.
669
-        if (! isset($this->_cpt_routes[ $this->_req_action ])) {
669
+        if ( ! isset($this->_cpt_routes[$this->_req_action])) {
670 670
             return;
671 671
         }
672 672
         $this->_cpt_route = true;
@@ -707,7 +707,7 @@  discard block
 block discarded – undo
707 707
             empty($this->_cpt_model_names)
708 708
             || (
709 709
                 ! $ignore_route_check
710
-                && ! isset($this->_cpt_routes[ $this->_req_action ])
710
+                && ! isset($this->_cpt_routes[$this->_req_action])
711 711
             )
712 712
             || (
713 713
                 $this->_cpt_model_obj instanceof EE_CPT_Base
@@ -725,11 +725,11 @@  discard block
 block discarded – undo
725 725
                 'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
726 726
             );
727 727
             $model_names       = $custom_post_types->getCustomPostTypeModelNames($post_type);
728
-            if (isset($model_names[ $post_type ])) {
729
-                $model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
728
+            if (isset($model_names[$post_type])) {
729
+                $model = EE_Registry::instance()->load_model($model_names[$post_type]);
730 730
             }
731 731
         } else {
732
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
732
+            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[$this->_req_action]);
733 733
         }
734 734
         if ($model instanceof EEM_Base) {
735 735
             $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
@@ -758,8 +758,8 @@  discard block
 block discarded – undo
758 758
         $current_route  = isset($this->_req_data['current_route'])
759 759
             ? $this->_req_data['current_route']
760 760
             : 'shouldneverwork';
761
-        $route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
762
-            ? $this->_cpt_routes[ $current_route ]
761
+        $route_to_check = $post_type && isset($this->_cpt_routes[$current_route])
762
+            ? $this->_cpt_routes[$current_route]
763 763
             : '';
764 764
         add_filter('get_delete_post_link', [$this, 'modify_delete_post_link'], 10, 3);
765 765
         add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 3);
@@ -768,10 +768,10 @@  discard block
 block discarded – undo
768 768
         }
769 769
         // now let's filter redirect if we're on a revision page and the revision is for an event CPT.
770 770
         $revision = isset($this->_req_data['revision']) ? $this->_req_data['revision'] : null;
771
-        if (! empty($revision)) {
771
+        if ( ! empty($revision)) {
772 772
             $action = isset($this->_req_data['action']) ? $this->_req_data['action'] : null;
773 773
             // doing a restore?
774
-            if (! empty($action) && $action === 'restore') {
774
+            if ( ! empty($action) && $action === 'restore') {
775 775
                 // get post for revision
776 776
                 $rev_post   = get_post($revision);
777 777
                 $rev_parent = get_post($rev_post->post_parent);
@@ -808,7 +808,7 @@  discard block
 block discarded – undo
808 808
     {
809 809
         $this->_set_model_object($post_id, true, 'trash');
810 810
         // if our cpt object isn't existent then get out immediately.
811
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
811
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
812 812
             return;
813 813
         }
814 814
         $this->trash_cpt_item($post_id);
@@ -827,7 +827,7 @@  discard block
 block discarded – undo
827 827
     {
828 828
         $this->_set_model_object($post_id, true, 'restore');
829 829
         // if our cpt object isn't existent then get out immediately.
830
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
830
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
831 831
             return;
832 832
         }
833 833
         $this->restore_cpt_item($post_id);
@@ -846,7 +846,7 @@  discard block
 block discarded – undo
846 846
     {
847 847
         $this->_set_model_object($post_id, true, 'delete');
848 848
         // if our cpt object isn't existent then get out immediately.
849
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
849
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
850 850
             return;
851 851
         }
852 852
         $this->delete_cpt_item($post_id);
@@ -865,7 +865,7 @@  discard block
 block discarded – undo
865 865
     {
866 866
         $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
867 867
         // verify event object
868
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
868
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
869 869
             throw new EE_Error(
870 870
                 sprintf(
871 871
                     esc_html__(
@@ -921,13 +921,13 @@  discard block
 block discarded – undo
921 921
         if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
922 922
             // setup custom post status object for localize script but only if we've got a cpt object
923 923
             $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
924
-            if (! empty($statuses)) {
924
+            if ( ! empty($statuses)) {
925 925
                 // get ALL statuses!
926 926
                 $statuses = $this->_cpt_model_obj->get_all_post_statuses();
927 927
                 // setup object
928 928
                 $ee_cpt_statuses = [];
929 929
                 foreach ($statuses as $status => $label) {
930
-                    $ee_cpt_statuses[ $status ] = [
930
+                    $ee_cpt_statuses[$status] = [
931 931
                         'label'      => $label,
932 932
                         'save_label' => sprintf(
933 933
                             wp_strip_all_tags(__('Save as %s', 'event_espresso')),
@@ -997,7 +997,7 @@  discard block
 block discarded – undo
997 997
             }
998 998
             if (
999 999
                 'default' != $this->_req_data['page_template']
1000
-                && ! isset($page_templates[ $this->_req_data['page_template'] ])
1000
+                && ! isset($page_templates[$this->_req_data['page_template']])
1001 1001
             ) {
1002 1002
                 EE_Error::add_error(
1003 1003
                     esc_html__('Invalid Page Template.', 'event_espresso'),
@@ -1028,7 +1028,7 @@  discard block
 block discarded – undo
1028 1028
     {
1029 1029
         // only do this if we're actually processing one of our CPTs
1030 1030
         // if our cpt object isn't existent then get out immediately.
1031
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1031
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
1032 1032
             return;
1033 1033
         }
1034 1034
         delete_post_meta($post_id, '_wp_trash_meta_status');
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
         // global action
1054 1054
         do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1055 1055
         // class specific action so you can limit hooking into a specific page.
1056
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1056
+        do_action('AHEE_EE_Admin_Page_CPT_'.get_class($this).'__restore_revision', $post_id, $revision_id);
1057 1057
     }
1058 1058
 
1059 1059
 
@@ -1081,11 +1081,11 @@  discard block
 block discarded – undo
1081 1081
     public function modify_current_screen()
1082 1082
     {
1083 1083
         // ONLY do this if the current page_route IS a cpt route
1084
-        if (! $this->_cpt_route) {
1084
+        if ( ! $this->_cpt_route) {
1085 1085
             return;
1086 1086
         }
1087 1087
         // routing things REALLY early b/c this is a cpt admin page
1088
-        set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1088
+        set_current_screen($this->_cpt_routes[$this->_req_action]);
1089 1089
         $this->_current_screen       = get_current_screen();
1090 1090
         $this->_current_screen->base = 'event-espresso';
1091 1091
         $this->_add_help_tabs(); // we make sure we add any help tabs back in!
@@ -1108,8 +1108,8 @@  discard block
 block discarded – undo
1108 1108
      */
1109 1109
     public function add_custom_editor_default_title($title)
1110 1110
     {
1111
-        return isset($this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ])
1112
-            ? $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1111
+        return isset($this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]])
1112
+            ? $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]]
1113 1113
             : $title;
1114 1114
     }
1115 1115
 
@@ -1125,10 +1125,10 @@  discard block
 block discarded – undo
1125 1125
      */
1126 1126
     public function add_shortlink_button_to_editor($shortlink, $id, $context, $allow_slugs)
1127 1127
     {
1128
-        if (! empty($id) && get_option('permalink_structure') !== '') {
1128
+        if ( ! empty($id) && get_option('permalink_structure') !== '') {
1129 1129
             $post = get_post($id);
1130 1130
             if (isset($post->post_type) && $this->page_slug === $post->post_type) {
1131
-                $shortlink = home_url('?p=' . $post->ID);
1131
+                $shortlink = home_url('?p='.$post->ID);
1132 1132
             }
1133 1133
         }
1134 1134
         return $shortlink;
@@ -1165,10 +1165,10 @@  discard block
 block discarded – undo
1165 1165
     {
1166 1166
         // we're also going to add the route value and the current page so we can direct autosave parsing correctly
1167 1167
         echo '
1168
-        <input type="hidden" name="ee_cpt_item_redirect_url" value="' . esc_url_raw($this->_admin_base_url) . '"/>
1168
+        <input type="hidden" name="ee_cpt_item_redirect_url" value="' . esc_url_raw($this->_admin_base_url).'"/>
1169 1169
         <div id="ee-cpt-hidden-inputs">
1170
-            <input type="hidden" id="current_route" name="current_route" value="' . esc_attr($this->_current_view) . '"/>
1171
-            <input type="hidden" id="current_page" name="current_page" value="' . esc_attr($this->page_slug) . '"/>
1170
+            <input type="hidden" id="current_route" name="current_route" value="' . esc_attr($this->_current_view).'"/>
1171
+            <input type="hidden" id="current_page" name="current_page" value="' . esc_attr($this->page_slug).'"/>
1172 1172
         </div>';
1173 1173
     }
1174 1174
 
@@ -1216,13 +1216,13 @@  discard block
 block discarded – undo
1216 1216
         $post = get_post($id);
1217 1217
         if (
1218 1218
             ! isset($this->_req_data['action'])
1219
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1220
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1219
+            || ! isset($this->_cpt_routes[$this->_req_data['action']])
1220
+            || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1221 1221
         ) {
1222 1222
             return $link;
1223 1223
         }
1224 1224
         $query_args = [
1225
-            'action' => $this->_cpt_edit_routes[ $post->post_type ] ?? 'edit',
1225
+            'action' => $this->_cpt_edit_routes[$post->post_type] ?? 'edit',
1226 1226
             'post'   => $id,
1227 1227
         ];
1228 1228
         return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
@@ -1246,16 +1246,16 @@  discard block
 block discarded – undo
1246 1246
 
1247 1247
         if (
1248 1248
             empty($this->_req_data['action'])
1249
-            || ! isset($this->_cpt_routes[ $this->_req_data['action'] ])
1249
+            || ! isset($this->_cpt_routes[$this->_req_data['action']])
1250 1250
             || ! $post instanceof WP_Post
1251
-            || $post->post_type !== $this->_cpt_routes[ $this->_req_data['action'] ]
1251
+            || $post->post_type !== $this->_cpt_routes[$this->_req_data['action']]
1252 1252
         ) {
1253 1253
             return $delete_link;
1254 1254
         }
1255 1255
         $this->_set_model_object($post->ID, true);
1256 1256
 
1257 1257
         // returns something like `trash_event` or `trash_attendee` or `trash_venue`
1258
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1258
+        $action = 'trash_'.str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1259 1259
 
1260 1260
         return EE_Admin_Page::add_query_args_and_nonce(
1261 1261
             [
@@ -1284,7 +1284,7 @@  discard block
 block discarded – undo
1284 1284
         // we DO have a match so let's setup the url
1285 1285
         // we have to get the post to determine our route
1286 1286
         $post       = get_post($post_id);
1287
-        $edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1287
+        $edit_route = $this->_cpt_edit_routes[$post->post_type];
1288 1288
         // shared query_args
1289 1289
         $query_args = ['action' => $edit_route, 'post' => $post_id];
1290 1290
         $admin_url  = $this->_admin_base_url;
@@ -1347,12 +1347,12 @@  discard block
 block discarded – undo
1347 1347
         $id       = empty($id) && is_object($post) ? $post->ID : null;
1348 1348
         $revision = $this->request->getRequestParam('revision', 0, 'int');
1349 1349
 
1350
-        $messages[ $post->post_type ] = [
1350
+        $messages[$post->post_type] = [
1351 1351
             0  => '', // Unused. Messages start at index 1.
1352 1352
             1  => sprintf(
1353 1353
                 esc_html__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1354 1354
                 $this->_cpt_object->labels->singular_name,
1355
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1355
+                '<a href="'.esc_url(get_permalink($id)).'">',
1356 1356
                 '</a>'
1357 1357
             ),
1358 1358
             2  => esc_html__('Custom field updated', 'event_espresso'),
@@ -1368,27 +1368,27 @@  discard block
 block discarded – undo
1368 1368
             6  => sprintf(
1369 1369
                 esc_html__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1370 1370
                 $this->_cpt_object->labels->singular_name,
1371
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1371
+                '<a href="'.esc_url(get_permalink($id)).'">',
1372 1372
                 '</a>'
1373 1373
             ),
1374 1374
             7  => sprintf(esc_html__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1375 1375
             8  => sprintf(
1376 1376
                 esc_html__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1377 1377
                 $this->_cpt_object->labels->singular_name,
1378
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1378
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))).'">',
1379 1379
                 '</a>'
1380 1380
             ),
1381 1381
             9  => sprintf(
1382 1382
                 esc_html__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1383 1383
                 $this->_cpt_object->labels->singular_name,
1384
-                '<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1385
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1384
+                '<strong>'.date_i18n('M j, Y @ G:i', strtotime($post->post_date)).'</strong>',
1385
+                '<a target="_blank" href="'.esc_url(get_permalink($id)),
1386 1386
                 '</a>'
1387 1387
             ),
1388 1388
             10 => sprintf(
1389 1389
                 esc_html__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1390 1390
                 $this->_cpt_object->labels->singular_name,
1391
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1391
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1392 1392
                 '</a>'
1393 1393
             ),
1394 1394
         ];
@@ -1406,10 +1406,10 @@  discard block
 block discarded – undo
1406 1406
     {
1407 1407
         // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1408 1408
         global $post, $title, $is_IE, $post_type, $post_type_object;
1409
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1409
+        $post_type        = $this->_cpt_routes[$this->_req_action];
1410 1410
         $post_type_object = $this->_cpt_object;
1411 1411
         $title            = $post_type_object->labels->add_new_item;
1412
-        $post             = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1412
+        $post             = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1413 1413
         add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1414 1414
         // modify the default editor title field with default title.
1415 1415
         add_filter('enter_title_here', [$this, 'add_custom_editor_default_title'], 10);
@@ -1434,8 +1434,8 @@  discard block
 block discarded – undo
1434 1434
             if ($creating) {
1435 1435
                 wp_enqueue_script('autosave');
1436 1436
             } elseif (
1437
-                isset($this->_cpt_routes[ $this->_req_data['action'] ])
1438
-                && ! isset($this->_labels['hide_add_button_on_cpt_route'][ $this->_req_data['action'] ])
1437
+                isset($this->_cpt_routes[$this->_req_data['action']])
1438
+                && ! isset($this->_labels['hide_add_button_on_cpt_route'][$this->_req_data['action']])
1439 1439
             ) {
1440 1440
                 $create_new_action = apply_filters(
1441 1441
                     'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
@@ -1450,7 +1450,7 @@  discard block
 block discarded – undo
1450 1450
                     'admin.php'
1451 1451
                 );
1452 1452
             }
1453
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1453
+            include_once WP_ADMIN_PATH.'edit-form-advanced.php';
1454 1454
         }
1455 1455
     }
1456 1456
 
@@ -1492,14 +1492,14 @@  discard block
 block discarded – undo
1492 1492
         }
1493 1493
 
1494 1494
         // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1495
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1495
+        $post_type        = $this->_cpt_routes[$this->_req_action];
1496 1496
         $post_type_object = $this->_cpt_object;
1497 1497
 
1498
-        if (! wp_check_post_lock($post->ID)) {
1498
+        if ( ! wp_check_post_lock($post->ID)) {
1499 1499
             wp_set_post_lock($post->ID);
1500 1500
         }
1501 1501
         add_action('admin_footer', '_admin_notice_post_locked');
1502
-        if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1502
+        if (post_type_supports($this->_cpt_routes[$this->_req_action], 'comments')) {
1503 1503
             wp_enqueue_script('admin-comments');
1504 1504
             enqueue_comment_hotkeys_js();
1505 1505
         }
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4180 added lines, -4180 removed lines patch added patch discarded remove patch
@@ -22,4264 +22,4264 @@
 block discarded – undo
22 22
  */
23 23
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
24 24
 {
25
-    /**
26
-     * @var EE_Admin_Config
27
-     */
28
-    protected $admin_config;
25
+	/**
26
+	 * @var EE_Admin_Config
27
+	 */
28
+	protected $admin_config;
29 29
 
30
-    /**
31
-     * @var LoaderInterface
32
-     */
33
-    protected $loader;
30
+	/**
31
+	 * @var LoaderInterface
32
+	 */
33
+	protected $loader;
34 34
 
35
-    /**
36
-     * @var RequestInterface
37
-     */
38
-    protected $request;
35
+	/**
36
+	 * @var RequestInterface
37
+	 */
38
+	protected $request;
39 39
 
40
-    // set in _init_page_props()
41
-    public $page_slug;
40
+	// set in _init_page_props()
41
+	public $page_slug;
42 42
 
43
-    public $page_label;
43
+	public $page_label;
44 44
 
45
-    public $page_folder;
45
+	public $page_folder;
46 46
 
47
-    // set in define_page_props()
48
-    protected $_admin_base_url;
47
+	// set in define_page_props()
48
+	protected $_admin_base_url;
49 49
 
50
-    protected $_admin_base_path;
50
+	protected $_admin_base_path;
51 51
 
52
-    protected $_admin_page_title;
52
+	protected $_admin_page_title;
53 53
 
54
-    protected $_labels;
54
+	protected $_labels;
55 55
 
56 56
 
57
-    // set early within EE_Admin_Init
58
-    protected $_wp_page_slug;
57
+	// set early within EE_Admin_Init
58
+	protected $_wp_page_slug;
59 59
 
60
-    // nav tabs
61
-    protected $_nav_tabs;
60
+	// nav tabs
61
+	protected $_nav_tabs;
62 62
 
63
-    protected $_default_nav_tab_name;
63
+	protected $_default_nav_tab_name;
64 64
 
65 65
 
66
-    // template variables (used by templates)
67
-    protected $_template_path;
66
+	// template variables (used by templates)
67
+	protected $_template_path;
68 68
 
69
-    protected $_column_template_path;
69
+	protected $_column_template_path;
70 70
 
71
-    /**
72
-     * @var array $_template_args
73
-     */
74
-    protected $_template_args = [];
71
+	/**
72
+	 * @var array $_template_args
73
+	 */
74
+	protected $_template_args = [];
75 75
 
76
-    /**
77
-     * this will hold the list table object for a given view.
78
-     *
79
-     * @var EE_Admin_List_Table $_list_table_object
80
-     */
81
-    protected $_list_table_object;
76
+	/**
77
+	 * this will hold the list table object for a given view.
78
+	 *
79
+	 * @var EE_Admin_List_Table $_list_table_object
80
+	 */
81
+	protected $_list_table_object;
82 82
 
83
-    // boolean
84
-    protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
83
+	// boolean
84
+	protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
85 85
 
86
-    protected $_routing;
86
+	protected $_routing;
87 87
 
88
-    // list table args
89
-    protected $_view;
88
+	// list table args
89
+	protected $_view;
90 90
 
91
-    protected $_views;
91
+	protected $_views;
92 92
 
93 93
 
94
-    // action => method pairs used for routing incoming requests
95
-    protected $_page_routes;
94
+	// action => method pairs used for routing incoming requests
95
+	protected $_page_routes;
96 96
 
97
-    /**
98
-     * @var array $_page_config
99
-     */
100
-    protected $_page_config;
97
+	/**
98
+	 * @var array $_page_config
99
+	 */
100
+	protected $_page_config;
101 101
 
102
-    /**
103
-     * the current page route and route config
104
-     *
105
-     * @var string $_route
106
-     */
107
-    protected $_route;
102
+	/**
103
+	 * the current page route and route config
104
+	 *
105
+	 * @var string $_route
106
+	 */
107
+	protected $_route;
108 108
 
109
-    /**
110
-     * @var string $_cpt_route
111
-     */
112
-    protected $_cpt_route;
109
+	/**
110
+	 * @var string $_cpt_route
111
+	 */
112
+	protected $_cpt_route;
113 113
 
114
-    /**
115
-     * @var array $_route_config
116
-     */
117
-    protected $_route_config;
114
+	/**
115
+	 * @var array $_route_config
116
+	 */
117
+	protected $_route_config;
118 118
 
119
-    /**
120
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
121
-     * actions.
122
-     *
123
-     * @since 4.6.x
124
-     * @var array.
125
-     */
126
-    protected $_default_route_query_args;
119
+	/**
120
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
121
+	 * actions.
122
+	 *
123
+	 * @since 4.6.x
124
+	 * @var array.
125
+	 */
126
+	protected $_default_route_query_args;
127 127
 
128
-    // set via request page and action args.
129
-    protected $_current_page;
128
+	// set via request page and action args.
129
+	protected $_current_page;
130 130
 
131
-    protected $_current_view;
131
+	protected $_current_view;
132 132
 
133
-    protected $_current_page_view_url;
133
+	protected $_current_page_view_url;
134 134
 
135
-    /**
136
-     * unprocessed value for the 'action' request param (default '')
137
-     *
138
-     * @var string
139
-     */
140
-    protected $raw_req_action = '';
135
+	/**
136
+	 * unprocessed value for the 'action' request param (default '')
137
+	 *
138
+	 * @var string
139
+	 */
140
+	protected $raw_req_action = '';
141 141
 
142
-    /**
143
-     * unprocessed value for the 'page' request param (default '')
144
-     *
145
-     * @var string
146
-     */
147
-    protected $raw_req_page = '';
148
-
149
-    /**
150
-     * sanitized request action (and nonce)
151
-     *
152
-     * @var string
153
-     */
154
-    protected $_req_action = '';
155
-
156
-    /**
157
-     * sanitized request action nonce
158
-     *
159
-     * @var string
160
-     */
161
-    protected $_req_nonce = '';
162
-
163
-    /**
164
-     * @var string
165
-     */
166
-    protected $_search_btn_label = '';
167
-
168
-    /**
169
-     * @var string
170
-     */
171
-    protected $_search_box_callback = '';
172
-
173
-    /**
174
-     * @var WP_Screen
175
-     */
176
-    protected $_current_screen;
177
-
178
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
179
-    protected $_hook_obj;
180
-
181
-    // for holding incoming request data
182
-    protected $_req_data = [];
183
-
184
-    // yes / no array for admin form fields
185
-    protected $_yes_no_values = [];
186
-
187
-    // some default things shared by all child classes
188
-    protected $_default_espresso_metaboxes = [
189
-        '_espresso_news_post_box',
190
-        '_espresso_links_post_box',
191
-        '_espresso_ratings_request',
192
-        '_espresso_sponsors_post_box',
193
-    ];
194
-
195
-    /**
196
-     * @var EE_Registry
197
-     */
198
-    protected $EE;
199
-
200
-
201
-    /**
202
-     * This is just a property that flags whether the given route is a caffeinated route or not.
203
-     *
204
-     * @var boolean
205
-     */
206
-    protected $_is_caf = false;
207
-
208
-    /**
209
-     * whether or not initializePage() has run
210
-     *
211
-     * @var boolean
212
-     */
213
-    protected $initialized = false;
214
-
215
-    /**
216
-     * @var FeatureFlags
217
-     */
218
-    protected $feature;
219
-
220
-
221
-    /**
222
-     * @var string
223
-     */
224
-    protected $class_name;
225
-
226
-    /**
227
-     * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
228
-     * then this would be the parent classname: Events_Admin_Page
229
-     *
230
-     * @var string
231
-     */
232
-    protected $base_class_name;
233
-
234
-
235
-    /**
236
-     * @Constructor
237
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
238
-     * @throws InvalidArgumentException
239
-     * @throws InvalidDataTypeException
240
-     * @throws InvalidInterfaceException
241
-     * @throws ReflectionException
242
-     */
243
-    public function __construct($routing = true)
244
-    {
245
-        $this->loader = LoaderFactory::getLoader();
246
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
247
-        $this->feature = $this->loader->getShared(FeatureFlags::class);
248
-        $this->request = $this->loader->getShared(RequestInterface::class);
249
-        // routing enabled?
250
-        $this->_routing = $routing;
251
-
252
-        $this->class_name = get_class($this);
253
-        $this->base_class_name = strpos($this->class_name, 'Extend_') === 0
254
-            ? str_replace('Extend_', '', $this->class_name)
255
-            : '';
256
-
257
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
258
-            $this->_is_caf = true;
259
-        }
260
-        $this->_yes_no_values = [
261
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
262
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
263
-        ];
264
-        // set the _req_data property.
265
-        $this->_req_data = $this->request->requestParams();
266
-    }
267
-
268
-
269
-    /**
270
-     * @return EE_Admin_Config
271
-     */
272
-    public function adminConfig(): EE_Admin_Config
273
-    {
274
-        return $this->admin_config;
275
-    }
276
-
277
-
278
-    /**
279
-     * @return FeatureFlags
280
-     */
281
-    public function feature(): FeatureFlags
282
-    {
283
-        return $this->feature;
284
-    }
285
-
286
-
287
-    /**
288
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
289
-     * for child classes that needed to set properties prior to these methods getting called,
290
-     * but also needed the parent class to have its construction completed as well.
291
-     * Bottom line is that constructors should ONLY be used for setting initial properties
292
-     * and any complex initialization logic should only run after instantiation is complete.
293
-     *
294
-     * This method gets called immediately after construction from within
295
-     *      EE_Admin_Page_Init::_initialize_admin_page()
296
-     *
297
-     * @throws EE_Error
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws ReflectionException
302
-     * @since $VID:$
303
-     */
304
-    public function initializePage()
305
-    {
306
-        if ($this->initialized) {
307
-            return;
308
-        }
309
-        // set initial page props (child method)
310
-        $this->_init_page_props();
311
-        // set global defaults
312
-        $this->_set_defaults();
313
-        // set early because incoming requests could be ajax related and we need to register those hooks.
314
-        $this->_global_ajax_hooks();
315
-        $this->_ajax_hooks();
316
-        // other_page_hooks have to be early too.
317
-        $this->_do_other_page_hooks();
318
-        // set up page dependencies
319
-        $this->_before_page_setup();
320
-        $this->_page_setup();
321
-        $this->initialized = true;
322
-    }
323
-
324
-
325
-    /**
326
-     * _init_page_props
327
-     * Child classes use to set at least the following properties:
328
-     * $page_slug.
329
-     * $page_label.
330
-     *
331
-     * @abstract
332
-     * @return void
333
-     */
334
-    abstract protected function _init_page_props();
335
-
336
-
337
-    /**
338
-     * _ajax_hooks
339
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
340
-     * Note: within the ajax callback methods.
341
-     *
342
-     * @abstract
343
-     * @return void
344
-     */
345
-    abstract protected function _ajax_hooks();
346
-
347
-
348
-    /**
349
-     * _define_page_props
350
-     * child classes define page properties in here.  Must include at least:
351
-     * $_admin_base_url = base_url for all admin pages
352
-     * $_admin_page_title = default admin_page_title for admin pages
353
-     * $_labels = array of default labels for various automatically generated elements:
354
-     *    array(
355
-     *        'buttons' => array(
356
-     *            'add' => esc_html__('label for add new button'),
357
-     *            'edit' => esc_html__('label for edit button'),
358
-     *            'delete' => esc_html__('label for delete button')
359
-     *            )
360
-     *        )
361
-     *
362
-     * @abstract
363
-     * @return void
364
-     */
365
-    abstract protected function _define_page_props();
366
-
367
-
368
-    /**
369
-     * _set_page_routes
370
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
371
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
372
-     * have a 'default' route. Here's the format
373
-     * $this->_page_routes = array(
374
-     *        'default' => array(
375
-     *            'func' => '_default_method_handling_route',
376
-     *            'args' => array('array','of','args'),
377
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
378
-     *            ajax request, backend processing)
379
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
380
-     *            headers route after.  The string you enter here should match the defined route reference for a
381
-     *            headers sent route.
382
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
383
-     *            this route.
384
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
385
-     *            checks).
386
-     *        ),
387
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
388
-     *        handling method.
389
-     *        )
390
-     * )
391
-     *
392
-     * @abstract
393
-     * @return void
394
-     */
395
-    abstract protected function _set_page_routes();
396
-
397
-
398
-    /**
399
-     * _set_page_config
400
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
401
-     * array corresponds to the page_route for the loaded page. Format:
402
-     * $this->_page_config = array(
403
-     *        'default' => array(
404
-     *            'labels' => array(
405
-     *                'buttons' => array(
406
-     *                    'add' => esc_html__('label for adding item'),
407
-     *                    'edit' => esc_html__('label for editing item'),
408
-     *                    'delete' => esc_html__('label for deleting item')
409
-     *                ),
410
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
411
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
412
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
413
-     *            _define_page_props() method
414
-     *            'nav' => array(
415
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
416
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
417
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
418
-     *                'order' => 10, //required to indicate tab position.
419
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
420
-     *                displayed then add this parameter.
421
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
422
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
423
-     *            metaboxes set for eventespresso admin pages.
424
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
425
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
426
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
427
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
428
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
429
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
430
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
431
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
432
-     *            want to display.
433
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
434
-     *                'tab_id' => array(
435
-     *                    'title' => 'tab_title',
436
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
437
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
438
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
439
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
440
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
441
-     *                    attempt to use the callback which should match the name of a method in the class
442
-     *                    ),
443
-     *                'tab2_id' => array(
444
-     *                    'title' => 'tab2 title',
445
-     *                    'filename' => 'file_name_2'
446
-     *                    'callback' => 'callback_method_for_content',
447
-     *                 ),
448
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
449
-     *            help tab area on an admin page. @return void
450
-     *
451
-     * @abstract
452
-     */
453
-    abstract protected function _set_page_config();
454
-
455
-
456
-    /**
457
-     * _add_screen_options
458
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
459
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
460
-     * to a particular view.
461
-     *
462
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
463
-     *         see also WP_Screen object documents...
464
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
465
-     * @abstract
466
-     * @return void
467
-     */
468
-    abstract protected function _add_screen_options();
469
-
470
-
471
-    /**
472
-     * _add_feature_pointers
473
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
474
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
475
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
476
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
477
-     * extended) also see:
478
-     *
479
-     * @link   http://eamann.com/tech/wordpress-portland/
480
-     * @abstract
481
-     * @return void
482
-     */
483
-    abstract protected function _add_feature_pointers();
484
-
485
-
486
-    /**
487
-     * load_scripts_styles
488
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
489
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
490
-     * scripts/styles per view by putting them in a dynamic function in this format
491
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
492
-     *
493
-     * @abstract
494
-     * @return void
495
-     */
496
-    abstract public function load_scripts_styles();
497
-
498
-
499
-    /**
500
-     * admin_init
501
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
502
-     * all pages/views loaded by child class.
503
-     *
504
-     * @abstract
505
-     * @return void
506
-     */
507
-    abstract public function admin_init();
508
-
509
-
510
-    /**
511
-     * admin_notices
512
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
513
-     * all pages/views loaded by child class.
514
-     *
515
-     * @abstract
516
-     * @return void
517
-     */
518
-    abstract public function admin_notices();
519
-
520
-
521
-    /**
522
-     * admin_footer_scripts
523
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
524
-     * will apply to all pages/views loaded by child class.
525
-     *
526
-     * @return void
527
-     */
528
-    abstract public function admin_footer_scripts();
529
-
530
-
531
-    /**
532
-     * admin_footer
533
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
534
-     * apply to all pages/views loaded by child class.
535
-     *
536
-     * @return void
537
-     */
538
-    public function admin_footer()
539
-    {
540
-    }
541
-
542
-
543
-    /**
544
-     * _global_ajax_hooks
545
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
546
-     * Note: within the ajax callback methods.
547
-     *
548
-     * @abstract
549
-     * @return void
550
-     */
551
-    protected function _global_ajax_hooks()
552
-    {
553
-        // for lazy loading of metabox content
554
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
555
-
556
-        add_action(
557
-            'wp_ajax_espresso_hide_status_change_notice',
558
-            [$this, 'hideStatusChangeNotice']
559
-        );
560
-        add_action(
561
-            'wp_ajax_nopriv_espresso_hide_status_change_notice',
562
-            [$this, 'hideStatusChangeNotice']
563
-        );
564
-    }
565
-
566
-
567
-    public function ajax_metabox_content()
568
-    {
569
-        $content_id  = $this->request->getRequestParam('contentid', '');
570
-        $content_url = $this->request->getRequestParam('contenturl', '', 'url');
571
-        EE_Admin_Page::cached_rss_display($content_id, $content_url);
572
-        wp_die();
573
-    }
574
-
575
-
576
-    public function hideStatusChangeNotice()
577
-    {
578
-        $response = [];
579
-        try {
580
-            /** @var StatusChangeNotice $status_change_notice */
581
-            $status_change_notice = $this->loader->getShared(
582
-                'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
583
-            );
584
-            $response['success'] = $status_change_notice->dismiss() > -1;
585
-        } catch (Exception $exception) {
586
-            $response['errors'] = $exception->getMessage();
587
-        }
588
-        echo wp_json_encode($response);
589
-        exit();
590
-    }
591
-
592
-
593
-    /**
594
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
595
-     *
596
-     * @return void
597
-     */
598
-    protected function _before_page_setup()
599
-    {
600
-        // default is to do nothing
601
-    }
602
-
603
-
604
-    /**
605
-     * Makes sure any things that need to be loaded early get handled.
606
-     * We also escape early here if the page requested doesn't match the object.
607
-     *
608
-     * @final
609
-     * @return void
610
-     * @throws EE_Error
611
-     * @throws InvalidArgumentException
612
-     * @throws ReflectionException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     */
616
-    final protected function _page_setup()
617
-    {
618
-        // requires?
619
-        // admin_init stuff - global - we're setting this REALLY early
620
-        // so if EE_Admin pages have to hook into other WP pages they can.
621
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
622
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
623
-        // next verify if we need to load anything...
624
-        $this->_current_page = $this->request->getRequestParam('page', '', 'key');
625
-        $this->page_folder   = strtolower(
626
-            str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
627
-        );
628
-        global $ee_menu_slugs;
629
-        $ee_menu_slugs = (array) $ee_menu_slugs;
630
-        if (
631
-            ! $this->request->isAjax()
632
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
633
-        ) {
634
-            return;
635
-        }
636
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
637
-        // we need to copy the action from the second to the first
638
-        $action     = $this->request->getRequestParam('action', '-1', 'key');
639
-        $action2    = $this->request->getRequestParam('action2', '-1', 'key');
640
-        $action     = $action !== '-1' ? $action : $action2;
641
-        $req_action = $action !== '-1' ? $action : 'default';
642
-
643
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
644
-        // then let's use the route as the action.
645
-        // This covers cases where we're coming in from a list table that isn't on the default route.
646
-        $route = $this->request->getRequestParam('route');
647
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
648
-            ? $route
649
-            : $req_action;
650
-
651
-        $this->_current_view = $this->_req_action;
652
-        $this->_req_nonce    = $this->_req_action . '_nonce';
653
-        $this->_define_page_props();
654
-        $this->_current_page_view_url = add_query_arg(
655
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
656
-            $this->_admin_base_url
657
-        );
658
-        // set page configs
659
-        $this->_set_page_routes();
660
-        $this->_set_page_config();
661
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
662
-        if ($this->request->requestParamIsSet('wp_referer')) {
663
-            $wp_referer = $this->request->getRequestParam('wp_referer');
664
-            if ($wp_referer) {
665
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
666
-            }
667
-        }
668
-        // for caffeinated and other extended functionality.
669
-        //  If there is a _extend_page_config method
670
-        // then let's run that to modify the all the various page configuration arrays
671
-        if (method_exists($this, '_extend_page_config')) {
672
-            $this->_extend_page_config();
673
-        }
674
-        // for CPT and other extended functionality.
675
-        // If there is an _extend_page_config_for_cpt
676
-        // then let's run that to modify all the various page configuration arrays.
677
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
678
-            $this->_extend_page_config_for_cpt();
679
-        }
680
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
681
-        $this->_page_routes = apply_filters(
682
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
683
-            $this->_page_routes,
684
-            $this
685
-        );
686
-        $this->_page_config = apply_filters(
687
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
688
-            $this->_page_config,
689
-            $this
690
-        );
691
-        if ($this->base_class_name !== '') {
692
-            $this->_page_routes = apply_filters(
693
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
694
-                $this->_page_routes,
695
-                $this
696
-            );
697
-            $this->_page_config = apply_filters(
698
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
699
-                $this->_page_config,
700
-                $this
701
-            );
702
-        }
703
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
706
-            add_action(
707
-                'AHEE__EE_Admin_Page__route_admin_request',
708
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
709
-                10,
710
-                2
711
-            );
712
-        }
713
-        // next route only if routing enabled
714
-        if ($this->_routing && ! $this->request->isAjax()) {
715
-            $this->_verify_routes();
716
-            // next let's just check user_access and kill if no access
717
-            $this->check_user_access();
718
-            if ($this->_is_UI_request) {
719
-                // admin_init stuff - global, all views for this page class, specific view
720
-                add_action('admin_init', [$this, 'admin_init'], 10);
721
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
723
-                }
724
-            } else {
725
-                // hijack regular WP loading and route admin request immediately
726
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
727
-                $this->route_admin_request();
728
-            }
729
-        }
730
-    }
731
-
732
-
733
-    /**
734
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
735
-     *
736
-     * @return void
737
-     * @throws EE_Error
738
-     */
739
-    private function _do_other_page_hooks()
740
-    {
741
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
742
-        foreach ($registered_pages as $page) {
743
-            // now let's setup the file name and class that should be present
744
-            $classname = str_replace('.class.php', '', $page);
745
-            // autoloaders should take care of loading file
746
-            if (! class_exists($classname)) {
747
-                $error_msg[] = sprintf(
748
-                    esc_html__(
749
-                        'Something went wrong with loading the %s admin hooks page.',
750
-                        'event_espresso'
751
-                    ),
752
-                    $page
753
-                );
754
-                $error_msg[] = $error_msg[0]
755
-                               . "\r\n"
756
-                               . sprintf(
757
-                                   esc_html__(
758
-                                       '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',
759
-                                       'event_espresso'
760
-                                   ),
761
-                                   $page,
762
-                                   '<br />',
763
-                                   '<strong>' . $classname . '</strong>'
764
-                               );
765
-                throw new EE_Error(implode('||', $error_msg));
766
-            }
767
-            // notice we are passing the instance of this class to the hook object.
768
-            $this->loader->getShared($classname, [$this]);
769
-        }
770
-    }
771
-
772
-
773
-    /**
774
-     * @throws ReflectionException
775
-     * @throws EE_Error
776
-     */
777
-    public function load_page_dependencies()
778
-    {
779
-        try {
780
-            $this->_load_page_dependencies();
781
-        } catch (EE_Error $e) {
782
-            $e->get_error();
783
-        }
784
-    }
785
-
786
-
787
-    /**
788
-     * load_page_dependencies
789
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
790
-     *
791
-     * @return void
792
-     * @throws DomainException
793
-     * @throws EE_Error
794
-     * @throws InvalidArgumentException
795
-     * @throws InvalidDataTypeException
796
-     * @throws InvalidInterfaceException
797
-     */
798
-    protected function _load_page_dependencies()
799
-    {
800
-        // let's set the current_screen and screen options to override what WP set
801
-        $this->_current_screen = get_current_screen();
802
-        // load admin_notices - global, page class, and view specific
803
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804
-        add_action('admin_notices', [$this, 'admin_notices'], 10);
805
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
807
-        }
808
-        // load network admin_notices - global, page class, and view specific
809
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
812
-        }
813
-        // this will save any per_page screen options if they are present
814
-        $this->_set_per_page_screen_options();
815
-        // setup list table properties
816
-        $this->_set_list_table();
817
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
818
-        // However in some cases the metaboxes will need to be added within a route handling callback.
819
-        $this->_add_registered_meta_boxes();
820
-        $this->_add_screen_columns();
821
-        // add screen options - global, page child class, and view specific
822
-        $this->_add_global_screen_options();
823
-        $this->_add_screen_options();
824
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
825
-        if (method_exists($this, $add_screen_options)) {
826
-            $this->{$add_screen_options}();
827
-        }
828
-        // add help tab(s) - set via page_config and qtips.
829
-        $this->_add_help_tabs();
830
-        $this->_add_qtips();
831
-        // add feature_pointers - global, page child class, and view specific
832
-        $this->_add_feature_pointers();
833
-        $this->_add_global_feature_pointers();
834
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
835
-        if (method_exists($this, $add_feature_pointer)) {
836
-            $this->{$add_feature_pointer}();
837
-        }
838
-        // enqueue scripts/styles - global, page class, and view specific
839
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
840
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
841
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
842
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
843
-        }
844
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
845
-        // admin_print_footer_scripts - global, page child class, and view specific.
846
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
847
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
848
-        // is a good use case. Notice the late priority we're giving these
849
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
850
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
851
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
852
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
853
-        }
854
-        // admin footer scripts
855
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
856
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
857
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
858
-            add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
859
-        }
860
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
861
-        // targeted hook
862
-        do_action(
863
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
864
-        );
865
-    }
866
-
867
-
868
-    /**
869
-     * _set_defaults
870
-     * This sets some global defaults for class properties.
871
-     */
872
-    private function _set_defaults()
873
-    {
874
-        $this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
875
-        $this->_event                = $this->_template_path = $this->_column_template_path = null;
876
-        $this->_nav_tabs             = $this->_views = $this->_page_routes = [];
877
-        $this->_page_config          = $this->_default_route_query_args = [];
878
-        $this->_default_nav_tab_name = 'overview';
879
-        // init template args
880
-        $this->_template_args = [
881
-            'admin_page_header'  => '',
882
-            'admin_page_content' => '',
883
-            'post_body_content'  => '',
884
-            'before_list_table'  => '',
885
-            'after_list_table'   => '',
886
-        ];
887
-    }
888
-
889
-
890
-    /**
891
-     * route_admin_request
892
-     *
893
-     * @return void
894
-     * @throws InvalidArgumentException
895
-     * @throws InvalidInterfaceException
896
-     * @throws InvalidDataTypeException
897
-     * @throws EE_Error
898
-     * @throws ReflectionException
899
-     * @see    _route_admin_request()
900
-     */
901
-    public function route_admin_request()
902
-    {
903
-        try {
904
-            $this->_route_admin_request();
905
-        } catch (EE_Error $e) {
906
-            $e->get_error();
907
-        }
908
-    }
909
-
910
-
911
-    public function set_wp_page_slug($wp_page_slug)
912
-    {
913
-        $this->_wp_page_slug = $wp_page_slug;
914
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
915
-        if (is_network_admin()) {
916
-            $this->_wp_page_slug .= '-network';
917
-        }
918
-    }
919
-
920
-
921
-    /**
922
-     * _verify_routes
923
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
924
-     * we know if we need to drop out.
925
-     *
926
-     * @return bool
927
-     * @throws EE_Error
928
-     */
929
-    protected function _verify_routes()
930
-    {
931
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
-        if (! $this->_current_page && ! $this->request->isAjax()) {
933
-            return false;
934
-        }
935
-        $this->_route = false;
936
-        // check that the page_routes array is not empty
937
-        if (empty($this->_page_routes)) {
938
-            // user error msg
939
-            $error_msg = sprintf(
940
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
941
-                $this->_admin_page_title
942
-            );
943
-            // developer error msg
944
-            $error_msg .= '||' . $error_msg
945
-                          . esc_html__(
946
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947
-                              'event_espresso'
948
-                          );
949
-            throw new EE_Error($error_msg);
950
-        }
951
-        // and that the requested page route exists
952
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
954
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
955
-        } else {
956
-            // user error msg
957
-            $error_msg = sprintf(
958
-                esc_html__(
959
-                    'The requested page route does not exist for the %s admin page.',
960
-                    'event_espresso'
961
-                ),
962
-                $this->_admin_page_title
963
-            );
964
-            // developer error msg
965
-            $error_msg .= '||' . $error_msg
966
-                          . sprintf(
967
-                              esc_html__(
968
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
969
-                                  'event_espresso'
970
-                              ),
971
-                              $this->_req_action
972
-                          );
973
-            throw new EE_Error($error_msg);
974
-        }
975
-        // and that a default route exists
976
-        if (! array_key_exists('default', $this->_page_routes)) {
977
-            // user error msg
978
-            $error_msg = sprintf(
979
-                esc_html__(
980
-                    'A default page route has not been set for the % admin page.',
981
-                    'event_espresso'
982
-                ),
983
-                $this->_admin_page_title
984
-            );
985
-            // developer error msg
986
-            $error_msg .= '||' . $error_msg
987
-                          . esc_html__(
988
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989
-                              'event_espresso'
990
-                          );
991
-            throw new EE_Error($error_msg);
992
-        }
993
-
994
-        // first lets' catch if the UI request has EVER been set.
995
-        if ($this->_is_UI_request === null) {
996
-            // lets set if this is a UI request or not.
997
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
998
-            // wait a minute... we might have a noheader in the route array
999
-            $this->_is_UI_request = ! (
1000
-                is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
1001
-            )
1002
-                ? $this->_is_UI_request
1003
-                : false;
1004
-        }
1005
-        $this->_set_current_labels();
1006
-        return true;
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1012
-     *
1013
-     * @param string $route the route name we're verifying
1014
-     * @return bool we'll throw an exception if this isn't a valid route.
1015
-     * @throws EE_Error
1016
-     */
1017
-    protected function _verify_route($route)
1018
-    {
1019
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
1020
-            return true;
1021
-        }
1022
-        // user error msg
1023
-        $error_msg = sprintf(
1024
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1025
-            $this->_admin_page_title
1026
-        );
1027
-        // developer error msg
1028
-        $error_msg .= '||' . $error_msg
1029
-                      . sprintf(
1030
-                          esc_html__(
1031
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1032
-                              'event_espresso'
1033
-                          ),
1034
-                          $route
1035
-                      );
1036
-        throw new EE_Error($error_msg);
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     * perform nonce verification
1042
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1043
-     * using this method (and save retyping!)
1044
-     *
1045
-     * @param string $nonce     The nonce sent
1046
-     * @param string $nonce_ref The nonce reference string (name0)
1047
-     * @return void
1048
-     * @throws EE_Error
1049
-     * @throws InvalidArgumentException
1050
-     * @throws InvalidDataTypeException
1051
-     * @throws InvalidInterfaceException
1052
-     */
1053
-    protected function _verify_nonce($nonce, $nonce_ref)
1054
-    {
1055
-        // verify nonce against expected value
1056
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1057
-            // these are not the droids you are looking for !!!
1058
-            $msg = sprintf(
1059
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
1060
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1061
-                '</a>'
1062
-            );
1063
-            if (WP_DEBUG) {
1064
-                $msg .= "\n  ";
1065
-                $msg .= sprintf(
1066
-                    esc_html__(
1067
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1068
-                        'event_espresso'
1069
-                    ),
1070
-                    __CLASS__
1071
-                );
1072
-            }
1073
-            if (! $this->request->isAjax()) {
1074
-                wp_die($msg);
1075
-            }
1076
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
-            $this->_return_json();
1078
-        }
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * _route_admin_request()
1084
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1085
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1086
-     * in the page routes and then will try to load the corresponding method.
1087
-     *
1088
-     * @return void
1089
-     * @throws EE_Error
1090
-     * @throws InvalidArgumentException
1091
-     * @throws InvalidDataTypeException
1092
-     * @throws InvalidInterfaceException
1093
-     * @throws ReflectionException
1094
-     */
1095
-    protected function _route_admin_request()
1096
-    {
1097
-        if (! $this->_is_UI_request) {
1098
-            $this->_verify_routes();
1099
-        }
1100
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1101
-        if ($this->_req_action !== 'default' && $nonce_check) {
1102
-            // set nonce from post data
1103
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1104
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1105
-        }
1106
-        // set the nav_tabs array but ONLY if this is  UI_request
1107
-        if ($this->_is_UI_request) {
1108
-            $this->_set_nav_tabs();
1109
-        }
1110
-        // grab callback function
1111
-        $func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1112
-        // check if callback has args
1113
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1114
-        $error_msg = '';
1115
-        // action right before calling route
1116
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119
-        }
1120
-        // strip _wp_http_referer from the server REQUEST_URI
1121
-        // else it grows in length on every submission due to recursion,
1122
-        // ultimately causing a "Request-URI Too Large" error
1123
-        $request_uri = remove_query_arg(
1124
-            '_wp_http_referer',
1125
-            wp_unslash($this->request->getServerParam('REQUEST_URI'))
1126
-        );
1127
-        // set new value in both our Request object and the super global
1128
-        $this->request->setServerParam('REQUEST_URI', $request_uri, true);
1129
-        if (! empty($func)) {
1130
-            if (is_array($func)) {
1131
-                [$class, $method] = $func;
1132
-            } elseif (strpos($func, '::') !== false) {
1133
-                [$class, $method] = explode('::', $func);
1134
-            } else {
1135
-                $class  = $this;
1136
-                $method = $func;
1137
-            }
1138
-            if (! (is_object($class) && $class === $this)) {
1139
-                // send along this admin page object for access by addons.
1140
-                $args['admin_page_object'] = $this;
1141
-            }
1142
-            if (
1143
-                // is it a method on a class that doesn't work?
1144
-                (
1145
-                    (
1146
-                        method_exists($class, $method)
1147
-                        && call_user_func_array([$class, $method], $args) === false
1148
-                    )
1149
-                    && (
1150
-                        // is it a standalone function that doesn't work?
1151
-                        function_exists($method)
1152
-                        && call_user_func_array(
1153
-                            $func,
1154
-                            array_merge(['admin_page_object' => $this], $args)
1155
-                        ) === false
1156
-                    )
1157
-                )
1158
-                || (
1159
-                    // is it neither a class method NOR a standalone function?
1160
-                    ! method_exists($class, $method)
1161
-                    && ! function_exists($method)
1162
-                )
1163
-            ) {
1164
-                // user error msg
1165
-                $error_msg = esc_html__(
1166
-                    'An error occurred. The  requested page route could not be found.',
1167
-                    'event_espresso'
1168
-                );
1169
-                // developer error msg
1170
-                $error_msg .= '||';
1171
-                $error_msg .= sprintf(
1172
-                    esc_html__(
1173
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1174
-                        'event_espresso'
1175
-                    ),
1176
-                    $method
1177
-                );
1178
-            }
1179
-            if (! empty($error_msg)) {
1180
-                throw new EE_Error($error_msg);
1181
-            }
1182
-        }
1183
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1184
-        // then we need to reset the routing properties to the new route.
1185
-        // 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.
1186
-        if (
1187
-            $this->_is_UI_request === false
1188
-            && is_array($this->_route)
1189
-            && ! empty($this->_route['headers_sent_route'])
1190
-        ) {
1191
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1192
-        }
1193
-    }
1194
-
1195
-
1196
-    /**
1197
-     * This method just allows the resetting of page properties in the case where a no headers
1198
-     * route redirects to a headers route in its route config.
1199
-     *
1200
-     * @param string $new_route New (non header) route to redirect to.
1201
-     * @return   void
1202
-     * @throws ReflectionException
1203
-     * @throws InvalidArgumentException
1204
-     * @throws InvalidInterfaceException
1205
-     * @throws InvalidDataTypeException
1206
-     * @throws EE_Error
1207
-     * @since   4.3.0
1208
-     */
1209
-    protected function _reset_routing_properties($new_route)
1210
-    {
1211
-        $this->_is_UI_request = true;
1212
-        // now we set the current route to whatever the headers_sent_route is set at
1213
-        $this->request->setRequestParam('action', $new_route);
1214
-        // rerun page setup
1215
-        $this->_page_setup();
1216
-    }
1217
-
1218
-
1219
-    /**
1220
-     * _add_query_arg
1221
-     * adds nonce to array of arguments then calls WP add_query_arg function
1222
-     *(internally just uses EEH_URL's function with the same name)
1223
-     *
1224
-     * @param array  $args
1225
-     * @param string $url
1226
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1227
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1228
-     *                                        Example usage: If the current page is:
1229
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1230
-     *                                        &action=default&event_id=20&month_range=March%202015
1231
-     *                                        &_wpnonce=5467821
1232
-     *                                        and you call:
1233
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1234
-     *                                        array(
1235
-     *                                        'action' => 'resend_something',
1236
-     *                                        'page=>espresso_registrations'
1237
-     *                                        ),
1238
-     *                                        $some_url,
1239
-     *                                        true
1240
-     *                                        );
1241
-     *                                        It will produce a url in this structure:
1242
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1243
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1244
-     *                                        month_range]=March%202015
1245
-     * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1246
-     * @return string
1247
-     */
1248
-    public static function add_query_args_and_nonce(
1249
-        $args = [],
1250
-        $url = '',
1251
-        $sticky = false,
1252
-        $exclude_nonce = false
1253
-    ) {
1254
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1255
-        if ($sticky) {
1256
-            /** @var RequestInterface $request */
1257
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1258
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1259
-            $request->unSetServerParam('_wp_http_referer', true);
1260
-            foreach ($request->requestParams() as $key => $value) {
1261
-                // do not add nonces
1262
-                if (strpos($key, 'nonce') !== false) {
1263
-                    continue;
1264
-                }
1265
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1266
-            }
1267
-        }
1268
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * This returns a generated link that will load the related help tab.
1274
-     *
1275
-     * @param string $help_tab_id the id for the connected help tab
1276
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1277
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1278
-     * @return string              generated link
1279
-     * @uses EEH_Template::get_help_tab_link()
1280
-     */
1281
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1282
-    {
1283
-        return EEH_Template::get_help_tab_link(
1284
-            $help_tab_id,
1285
-            $this->page_slug,
1286
-            $this->_req_action,
1287
-            $icon_style,
1288
-            $help_text
1289
-        );
1290
-    }
1291
-
1292
-
1293
-    /**
1294
-     * _add_help_tabs
1295
-     * Note child classes define their help tabs within the page_config array.
1296
-     *
1297
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1298
-     * @return void
1299
-     * @throws DomainException
1300
-     * @throws EE_Error
1301
-     * @throws ReflectionException
1302
-     */
1303
-    protected function _add_help_tabs()
1304
-    {
1305
-        if (isset($this->_page_config[ $this->_req_action ])) {
1306
-            $config = $this->_page_config[ $this->_req_action ];
1307
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1308
-            if (is_array($config) && isset($config['help_sidebar'])) {
1309
-                // check that the callback given is valid
1310
-                if (! method_exists($this, $config['help_sidebar'])) {
1311
-                    throw new EE_Error(
1312
-                        sprintf(
1313
-                            esc_html__(
1314
-                                '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',
1315
-                                'event_espresso'
1316
-                            ),
1317
-                            $config['help_sidebar'],
1318
-                            $this->class_name
1319
-                        )
1320
-                    );
1321
-                }
1322
-                $content = apply_filters(
1323
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1324
-                    $this->{$config['help_sidebar']}()
1325
-                );
1326
-                $this->_current_screen->set_help_sidebar($content);
1327
-            }
1328
-            if (! isset($config['help_tabs'])) {
1329
-                return;
1330
-            } //no help tabs for this route
1331
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1332
-                // we're here so there ARE help tabs!
1333
-                // make sure we've got what we need
1334
-                if (! isset($cfg['title'])) {
1335
-                    throw new EE_Error(
1336
-                        esc_html__(
1337
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1338
-                            'event_espresso'
1339
-                        )
1340
-                    );
1341
-                }
1342
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1343
-                    throw new EE_Error(
1344
-                        esc_html__(
1345
-                            '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',
1346
-                            'event_espresso'
1347
-                        )
1348
-                    );
1349
-                }
1350
-                // first priority goes to content.
1351
-                if (! empty($cfg['content'])) {
1352
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1353
-                    // second priority goes to filename
1354
-                } elseif (! empty($cfg['filename'])) {
1355
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1356
-                    // 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)
1357
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1358
-                                                             . basename($this->_get_dir())
1359
-                                                             . '/help_tabs/'
1360
-                                                             . $cfg['filename']
1361
-                                                             . '.help_tab.php' : $file_path;
1362
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1363
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1364
-                        EE_Error::add_error(
1365
-                            sprintf(
1366
-                                esc_html__(
1367
-                                    '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',
1368
-                                    'event_espresso'
1369
-                                ),
1370
-                                $tab_id,
1371
-                                key($config),
1372
-                                $file_path
1373
-                            ),
1374
-                            __FILE__,
1375
-                            __FUNCTION__,
1376
-                            __LINE__
1377
-                        );
1378
-                        return;
1379
-                    }
1380
-                    $template_args['admin_page_obj'] = $this;
1381
-                    $content                         = EEH_Template::display_template(
1382
-                        $file_path,
1383
-                        $template_args,
1384
-                        true
1385
-                    );
1386
-                } else {
1387
-                    $content = '';
1388
-                }
1389
-                // check if callback is valid
1390
-                if (
1391
-                    empty($content)
1392
-                    && (
1393
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1394
-                    )
1395
-                ) {
1396
-                    EE_Error::add_error(
1397
-                        sprintf(
1398
-                            esc_html__(
1399
-                                '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.',
1400
-                                'event_espresso'
1401
-                            ),
1402
-                            $cfg['title']
1403
-                        ),
1404
-                        __FILE__,
1405
-                        __FUNCTION__,
1406
-                        __LINE__
1407
-                    );
1408
-                    return;
1409
-                }
1410
-                // setup config array for help tab method
1411
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1412
-                $_ht = [
1413
-                    'id'       => $id,
1414
-                    'title'    => $cfg['title'],
1415
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1416
-                    'content'  => $content,
1417
-                ];
1418
-                $this->_current_screen->add_help_tab($_ht);
1419
-            }
1420
-        }
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * This simply sets up any qtips that have been defined in the page config
1426
-     *
1427
-     * @return void
1428
-     * @throws ReflectionException
1429
-     * @throws EE_Error
1430
-     */
1431
-    protected function _add_qtips()
1432
-    {
1433
-        if (isset($this->_route_config['qtips'])) {
1434
-            $qtips = (array) $this->_route_config['qtips'];
1435
-            // load qtip loader
1436
-            $path = [
1437
-                $this->_get_dir() . '/qtips/',
1438
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1439
-            ];
1440
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1441
-        }
1442
-    }
1443
-
1444
-
1445
-    /**
1446
-     * _set_nav_tabs
1447
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1448
-     * wish to add additional tabs or modify accordingly.
1449
-     *
1450
-     * @return void
1451
-     * @throws InvalidArgumentException
1452
-     * @throws InvalidInterfaceException
1453
-     * @throws InvalidDataTypeException
1454
-     */
1455
-    protected function _set_nav_tabs()
1456
-    {
1457
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1458
-        $i = 0;
1459
-        foreach ($this->_page_config as $slug => $config) {
1460
-            if (! is_array($config) || empty($config['nav'])) {
1461
-                continue;
1462
-            }
1463
-            // no nav tab for this config
1464
-            // check for persistent flag
1465
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1466
-                // nav tab is only to appear when route requested.
1467
-                continue;
1468
-            }
1469
-            if (! $this->check_user_access($slug, true)) {
1470
-                // no nav tab because current user does not have access.
1471
-                continue;
1472
-            }
1473
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1474
-            $this->_nav_tabs[ $slug ] = [
1475
-                'url'       => isset($config['nav']['url'])
1476
-                    ? $config['nav']['url']
1477
-                    : EE_Admin_Page::add_query_args_and_nonce(
1478
-                        ['action' => $slug],
1479
-                        $this->_admin_base_url
1480
-                    ),
1481
-                'link_text' => isset($config['nav']['label'])
1482
-                    ? $config['nav']['label']
1483
-                    : ucwords(
1484
-                        str_replace('_', ' ', $slug)
1485
-                    ),
1486
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1487
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1488
-            ];
1489
-            $i++;
1490
-        }
1491
-        // if $this->_nav_tabs is empty then lets set the default
1492
-        if (empty($this->_nav_tabs)) {
1493
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1494
-                'url'       => $this->_admin_base_url,
1495
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1496
-                'css_class' => 'nav-tab-active',
1497
-                'order'     => 10,
1498
-            ];
1499
-        }
1500
-        // now let's sort the tabs according to order
1501
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * _set_current_labels
1507
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1508
-     * property array
1509
-     *
1510
-     * @return void
1511
-     */
1512
-    private function _set_current_labels()
1513
-    {
1514
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1515
-            foreach ($this->_route_config['labels'] as $label => $text) {
1516
-                if (is_array($text)) {
1517
-                    foreach ($text as $sublabel => $subtext) {
1518
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1519
-                    }
1520
-                } else {
1521
-                    $this->_labels[ $label ] = $text;
1522
-                }
1523
-            }
1524
-        }
1525
-    }
1526
-
1527
-
1528
-    /**
1529
-     *        verifies user access for this admin page
1530
-     *
1531
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1532
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1533
-     *                               return false if verify fail.
1534
-     * @return bool
1535
-     * @throws InvalidArgumentException
1536
-     * @throws InvalidDataTypeException
1537
-     * @throws InvalidInterfaceException
1538
-     */
1539
-    public function check_user_access($route_to_check = '', $verify_only = false)
1540
-    {
1541
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1542
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1543
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1544
-                          && is_array(
1545
-                              $this->_page_routes[ $route_to_check ]
1546
-                          )
1547
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1548
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1549
-        if (empty($capability) && empty($route_to_check)) {
1550
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1551
-                : $this->_route['capability'];
1552
-        } else {
1553
-            $capability = empty($capability) ? 'manage_options' : $capability;
1554
-        }
1555
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1556
-        if (
1557
-            ! $this->request->isAjax()
1558
-            && (
1559
-                ! function_exists('is_admin')
1560
-                || ! EE_Registry::instance()->CAP->current_user_can(
1561
-                    $capability,
1562
-                    $this->page_slug
1563
-                    . '_'
1564
-                    . $route_to_check,
1565
-                    $id
1566
-                )
1567
-            )
1568
-        ) {
1569
-            if ($verify_only) {
1570
-                return false;
1571
-            }
1572
-            if (is_user_logged_in()) {
1573
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1574
-            } else {
1575
-                return false;
1576
-            }
1577
-        }
1578
-        return true;
1579
-    }
1580
-
1581
-
1582
-    /**
1583
-     * @param string                 $box_id
1584
-     * @param string                 $title
1585
-     * @param callable|string|null   $callback
1586
-     * @param string|array|WP_Screen $screen
1587
-     * @param string                 $context
1588
-     * @param string                 $priority
1589
-     * @param array|null             $callback_args
1590
-     */
1591
-    protected function addMetaBox(
1592
-        string $box_id,
1593
-        string $title,
1594
-        $callback,
1595
-        $screen,
1596
-        string $context = 'normal',
1597
-        string $priority = 'default',
1598
-        ?array $callback_args = null
1599
-    ) {
1600
-        if (! is_callable($callback)) {
1601
-            return;
1602
-        }
1603
-
1604
-        add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1605
-        add_filter(
1606
-            "postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1607
-            function ($classes) {
1608
-                array_push($classes, 'ee-admin-container');
1609
-                return $classes;
1610
-            }
1611
-        );
1612
-    }
1613
-
1614
-
1615
-    /**
1616
-     * admin_init_global
1617
-     * This runs all the code that we want executed within the WP admin_init hook.
1618
-     * This method executes for ALL EE Admin pages.
1619
-     *
1620
-     * @return void
1621
-     */
1622
-    public function admin_init_global()
1623
-    {
1624
-    }
1625
-
1626
-
1627
-    /**
1628
-     * wp_loaded_global
1629
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1630
-     * EE_Admin page and will execute on every EE Admin Page load
1631
-     *
1632
-     * @return void
1633
-     */
1634
-    public function wp_loaded()
1635
-    {
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     * admin_notices
1641
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1642
-     * ALL EE_Admin pages.
1643
-     *
1644
-     * @return void
1645
-     */
1646
-    public function admin_notices_global()
1647
-    {
1648
-        $this->_display_no_javascript_warning();
1649
-        $this->_display_espresso_notices();
1650
-    }
1651
-
1652
-
1653
-    public function network_admin_notices_global()
1654
-    {
1655
-        $this->_display_no_javascript_warning();
1656
-        $this->_display_espresso_notices();
1657
-    }
1658
-
1659
-
1660
-    /**
1661
-     * admin_footer_scripts_global
1662
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1663
-     * will apply on ALL EE_Admin pages.
1664
-     *
1665
-     * @return void
1666
-     */
1667
-    public function admin_footer_scripts_global()
1668
-    {
1669
-        $this->_add_admin_page_ajax_loading_img();
1670
-        $this->_add_admin_page_overlay();
1671
-        // if metaboxes are present we need to add the nonce field
1672
-        if (
1673
-            isset($this->_route_config['metaboxes'])
1674
-            || isset($this->_route_config['list_table'])
1675
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1676
-        ) {
1677
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1678
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1679
-        }
1680
-    }
1681
-
1682
-
1683
-    /**
1684
-     * admin_footer_global
1685
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1686
-     * This particular method will apply on ALL EE_Admin Pages.
1687
-     *
1688
-     * @return void
1689
-     */
1690
-    public function admin_footer_global()
1691
-    {
1692
-        // dialog container for dialog helper
1693
-        echo '
142
+	/**
143
+	 * unprocessed value for the 'page' request param (default '')
144
+	 *
145
+	 * @var string
146
+	 */
147
+	protected $raw_req_page = '';
148
+
149
+	/**
150
+	 * sanitized request action (and nonce)
151
+	 *
152
+	 * @var string
153
+	 */
154
+	protected $_req_action = '';
155
+
156
+	/**
157
+	 * sanitized request action nonce
158
+	 *
159
+	 * @var string
160
+	 */
161
+	protected $_req_nonce = '';
162
+
163
+	/**
164
+	 * @var string
165
+	 */
166
+	protected $_search_btn_label = '';
167
+
168
+	/**
169
+	 * @var string
170
+	 */
171
+	protected $_search_box_callback = '';
172
+
173
+	/**
174
+	 * @var WP_Screen
175
+	 */
176
+	protected $_current_screen;
177
+
178
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
179
+	protected $_hook_obj;
180
+
181
+	// for holding incoming request data
182
+	protected $_req_data = [];
183
+
184
+	// yes / no array for admin form fields
185
+	protected $_yes_no_values = [];
186
+
187
+	// some default things shared by all child classes
188
+	protected $_default_espresso_metaboxes = [
189
+		'_espresso_news_post_box',
190
+		'_espresso_links_post_box',
191
+		'_espresso_ratings_request',
192
+		'_espresso_sponsors_post_box',
193
+	];
194
+
195
+	/**
196
+	 * @var EE_Registry
197
+	 */
198
+	protected $EE;
199
+
200
+
201
+	/**
202
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
203
+	 *
204
+	 * @var boolean
205
+	 */
206
+	protected $_is_caf = false;
207
+
208
+	/**
209
+	 * whether or not initializePage() has run
210
+	 *
211
+	 * @var boolean
212
+	 */
213
+	protected $initialized = false;
214
+
215
+	/**
216
+	 * @var FeatureFlags
217
+	 */
218
+	protected $feature;
219
+
220
+
221
+	/**
222
+	 * @var string
223
+	 */
224
+	protected $class_name;
225
+
226
+	/**
227
+	 * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
228
+	 * then this would be the parent classname: Events_Admin_Page
229
+	 *
230
+	 * @var string
231
+	 */
232
+	protected $base_class_name;
233
+
234
+
235
+	/**
236
+	 * @Constructor
237
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
238
+	 * @throws InvalidArgumentException
239
+	 * @throws InvalidDataTypeException
240
+	 * @throws InvalidInterfaceException
241
+	 * @throws ReflectionException
242
+	 */
243
+	public function __construct($routing = true)
244
+	{
245
+		$this->loader = LoaderFactory::getLoader();
246
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
247
+		$this->feature = $this->loader->getShared(FeatureFlags::class);
248
+		$this->request = $this->loader->getShared(RequestInterface::class);
249
+		// routing enabled?
250
+		$this->_routing = $routing;
251
+
252
+		$this->class_name = get_class($this);
253
+		$this->base_class_name = strpos($this->class_name, 'Extend_') === 0
254
+			? str_replace('Extend_', '', $this->class_name)
255
+			: '';
256
+
257
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
258
+			$this->_is_caf = true;
259
+		}
260
+		$this->_yes_no_values = [
261
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
262
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
263
+		];
264
+		// set the _req_data property.
265
+		$this->_req_data = $this->request->requestParams();
266
+	}
267
+
268
+
269
+	/**
270
+	 * @return EE_Admin_Config
271
+	 */
272
+	public function adminConfig(): EE_Admin_Config
273
+	{
274
+		return $this->admin_config;
275
+	}
276
+
277
+
278
+	/**
279
+	 * @return FeatureFlags
280
+	 */
281
+	public function feature(): FeatureFlags
282
+	{
283
+		return $this->feature;
284
+	}
285
+
286
+
287
+	/**
288
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
289
+	 * for child classes that needed to set properties prior to these methods getting called,
290
+	 * but also needed the parent class to have its construction completed as well.
291
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
292
+	 * and any complex initialization logic should only run after instantiation is complete.
293
+	 *
294
+	 * This method gets called immediately after construction from within
295
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
296
+	 *
297
+	 * @throws EE_Error
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws ReflectionException
302
+	 * @since $VID:$
303
+	 */
304
+	public function initializePage()
305
+	{
306
+		if ($this->initialized) {
307
+			return;
308
+		}
309
+		// set initial page props (child method)
310
+		$this->_init_page_props();
311
+		// set global defaults
312
+		$this->_set_defaults();
313
+		// set early because incoming requests could be ajax related and we need to register those hooks.
314
+		$this->_global_ajax_hooks();
315
+		$this->_ajax_hooks();
316
+		// other_page_hooks have to be early too.
317
+		$this->_do_other_page_hooks();
318
+		// set up page dependencies
319
+		$this->_before_page_setup();
320
+		$this->_page_setup();
321
+		$this->initialized = true;
322
+	}
323
+
324
+
325
+	/**
326
+	 * _init_page_props
327
+	 * Child classes use to set at least the following properties:
328
+	 * $page_slug.
329
+	 * $page_label.
330
+	 *
331
+	 * @abstract
332
+	 * @return void
333
+	 */
334
+	abstract protected function _init_page_props();
335
+
336
+
337
+	/**
338
+	 * _ajax_hooks
339
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
340
+	 * Note: within the ajax callback methods.
341
+	 *
342
+	 * @abstract
343
+	 * @return void
344
+	 */
345
+	abstract protected function _ajax_hooks();
346
+
347
+
348
+	/**
349
+	 * _define_page_props
350
+	 * child classes define page properties in here.  Must include at least:
351
+	 * $_admin_base_url = base_url for all admin pages
352
+	 * $_admin_page_title = default admin_page_title for admin pages
353
+	 * $_labels = array of default labels for various automatically generated elements:
354
+	 *    array(
355
+	 *        'buttons' => array(
356
+	 *            'add' => esc_html__('label for add new button'),
357
+	 *            'edit' => esc_html__('label for edit button'),
358
+	 *            'delete' => esc_html__('label for delete button')
359
+	 *            )
360
+	 *        )
361
+	 *
362
+	 * @abstract
363
+	 * @return void
364
+	 */
365
+	abstract protected function _define_page_props();
366
+
367
+
368
+	/**
369
+	 * _set_page_routes
370
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
371
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
372
+	 * have a 'default' route. Here's the format
373
+	 * $this->_page_routes = array(
374
+	 *        'default' => array(
375
+	 *            'func' => '_default_method_handling_route',
376
+	 *            'args' => array('array','of','args'),
377
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
378
+	 *            ajax request, backend processing)
379
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
380
+	 *            headers route after.  The string you enter here should match the defined route reference for a
381
+	 *            headers sent route.
382
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
383
+	 *            this route.
384
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
385
+	 *            checks).
386
+	 *        ),
387
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
388
+	 *        handling method.
389
+	 *        )
390
+	 * )
391
+	 *
392
+	 * @abstract
393
+	 * @return void
394
+	 */
395
+	abstract protected function _set_page_routes();
396
+
397
+
398
+	/**
399
+	 * _set_page_config
400
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
401
+	 * array corresponds to the page_route for the loaded page. Format:
402
+	 * $this->_page_config = array(
403
+	 *        'default' => array(
404
+	 *            'labels' => array(
405
+	 *                'buttons' => array(
406
+	 *                    'add' => esc_html__('label for adding item'),
407
+	 *                    'edit' => esc_html__('label for editing item'),
408
+	 *                    'delete' => esc_html__('label for deleting item')
409
+	 *                ),
410
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
411
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
412
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
413
+	 *            _define_page_props() method
414
+	 *            'nav' => array(
415
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
416
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
417
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
418
+	 *                'order' => 10, //required to indicate tab position.
419
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
420
+	 *                displayed then add this parameter.
421
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
422
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
423
+	 *            metaboxes set for eventespresso admin pages.
424
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
425
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
426
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
427
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
428
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
429
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
430
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
431
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
432
+	 *            want to display.
433
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
434
+	 *                'tab_id' => array(
435
+	 *                    'title' => 'tab_title',
436
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
437
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
438
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
439
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
440
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
441
+	 *                    attempt to use the callback which should match the name of a method in the class
442
+	 *                    ),
443
+	 *                'tab2_id' => array(
444
+	 *                    'title' => 'tab2 title',
445
+	 *                    'filename' => 'file_name_2'
446
+	 *                    'callback' => 'callback_method_for_content',
447
+	 *                 ),
448
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
449
+	 *            help tab area on an admin page. @return void
450
+	 *
451
+	 * @abstract
452
+	 */
453
+	abstract protected function _set_page_config();
454
+
455
+
456
+	/**
457
+	 * _add_screen_options
458
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
459
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
460
+	 * to a particular view.
461
+	 *
462
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
463
+	 *         see also WP_Screen object documents...
464
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
465
+	 * @abstract
466
+	 * @return void
467
+	 */
468
+	abstract protected function _add_screen_options();
469
+
470
+
471
+	/**
472
+	 * _add_feature_pointers
473
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
474
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
475
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
476
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
477
+	 * extended) also see:
478
+	 *
479
+	 * @link   http://eamann.com/tech/wordpress-portland/
480
+	 * @abstract
481
+	 * @return void
482
+	 */
483
+	abstract protected function _add_feature_pointers();
484
+
485
+
486
+	/**
487
+	 * load_scripts_styles
488
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
489
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
490
+	 * scripts/styles per view by putting them in a dynamic function in this format
491
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
492
+	 *
493
+	 * @abstract
494
+	 * @return void
495
+	 */
496
+	abstract public function load_scripts_styles();
497
+
498
+
499
+	/**
500
+	 * admin_init
501
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
502
+	 * all pages/views loaded by child class.
503
+	 *
504
+	 * @abstract
505
+	 * @return void
506
+	 */
507
+	abstract public function admin_init();
508
+
509
+
510
+	/**
511
+	 * admin_notices
512
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
513
+	 * all pages/views loaded by child class.
514
+	 *
515
+	 * @abstract
516
+	 * @return void
517
+	 */
518
+	abstract public function admin_notices();
519
+
520
+
521
+	/**
522
+	 * admin_footer_scripts
523
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
524
+	 * will apply to all pages/views loaded by child class.
525
+	 *
526
+	 * @return void
527
+	 */
528
+	abstract public function admin_footer_scripts();
529
+
530
+
531
+	/**
532
+	 * admin_footer
533
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
534
+	 * apply to all pages/views loaded by child class.
535
+	 *
536
+	 * @return void
537
+	 */
538
+	public function admin_footer()
539
+	{
540
+	}
541
+
542
+
543
+	/**
544
+	 * _global_ajax_hooks
545
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
546
+	 * Note: within the ajax callback methods.
547
+	 *
548
+	 * @abstract
549
+	 * @return void
550
+	 */
551
+	protected function _global_ajax_hooks()
552
+	{
553
+		// for lazy loading of metabox content
554
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
555
+
556
+		add_action(
557
+			'wp_ajax_espresso_hide_status_change_notice',
558
+			[$this, 'hideStatusChangeNotice']
559
+		);
560
+		add_action(
561
+			'wp_ajax_nopriv_espresso_hide_status_change_notice',
562
+			[$this, 'hideStatusChangeNotice']
563
+		);
564
+	}
565
+
566
+
567
+	public function ajax_metabox_content()
568
+	{
569
+		$content_id  = $this->request->getRequestParam('contentid', '');
570
+		$content_url = $this->request->getRequestParam('contenturl', '', 'url');
571
+		EE_Admin_Page::cached_rss_display($content_id, $content_url);
572
+		wp_die();
573
+	}
574
+
575
+
576
+	public function hideStatusChangeNotice()
577
+	{
578
+		$response = [];
579
+		try {
580
+			/** @var StatusChangeNotice $status_change_notice */
581
+			$status_change_notice = $this->loader->getShared(
582
+				'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
583
+			);
584
+			$response['success'] = $status_change_notice->dismiss() > -1;
585
+		} catch (Exception $exception) {
586
+			$response['errors'] = $exception->getMessage();
587
+		}
588
+		echo wp_json_encode($response);
589
+		exit();
590
+	}
591
+
592
+
593
+	/**
594
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
595
+	 *
596
+	 * @return void
597
+	 */
598
+	protected function _before_page_setup()
599
+	{
600
+		// default is to do nothing
601
+	}
602
+
603
+
604
+	/**
605
+	 * Makes sure any things that need to be loaded early get handled.
606
+	 * We also escape early here if the page requested doesn't match the object.
607
+	 *
608
+	 * @final
609
+	 * @return void
610
+	 * @throws EE_Error
611
+	 * @throws InvalidArgumentException
612
+	 * @throws ReflectionException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 */
616
+	final protected function _page_setup()
617
+	{
618
+		// requires?
619
+		// admin_init stuff - global - we're setting this REALLY early
620
+		// so if EE_Admin pages have to hook into other WP pages they can.
621
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
622
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
623
+		// next verify if we need to load anything...
624
+		$this->_current_page = $this->request->getRequestParam('page', '', 'key');
625
+		$this->page_folder   = strtolower(
626
+			str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
627
+		);
628
+		global $ee_menu_slugs;
629
+		$ee_menu_slugs = (array) $ee_menu_slugs;
630
+		if (
631
+			! $this->request->isAjax()
632
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
633
+		) {
634
+			return;
635
+		}
636
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
637
+		// we need to copy the action from the second to the first
638
+		$action     = $this->request->getRequestParam('action', '-1', 'key');
639
+		$action2    = $this->request->getRequestParam('action2', '-1', 'key');
640
+		$action     = $action !== '-1' ? $action : $action2;
641
+		$req_action = $action !== '-1' ? $action : 'default';
642
+
643
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
644
+		// then let's use the route as the action.
645
+		// This covers cases where we're coming in from a list table that isn't on the default route.
646
+		$route = $this->request->getRequestParam('route');
647
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
648
+			? $route
649
+			: $req_action;
650
+
651
+		$this->_current_view = $this->_req_action;
652
+		$this->_req_nonce    = $this->_req_action . '_nonce';
653
+		$this->_define_page_props();
654
+		$this->_current_page_view_url = add_query_arg(
655
+			['page' => $this->_current_page, 'action' => $this->_current_view],
656
+			$this->_admin_base_url
657
+		);
658
+		// set page configs
659
+		$this->_set_page_routes();
660
+		$this->_set_page_config();
661
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
662
+		if ($this->request->requestParamIsSet('wp_referer')) {
663
+			$wp_referer = $this->request->getRequestParam('wp_referer');
664
+			if ($wp_referer) {
665
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
666
+			}
667
+		}
668
+		// for caffeinated and other extended functionality.
669
+		//  If there is a _extend_page_config method
670
+		// then let's run that to modify the all the various page configuration arrays
671
+		if (method_exists($this, '_extend_page_config')) {
672
+			$this->_extend_page_config();
673
+		}
674
+		// for CPT and other extended functionality.
675
+		// If there is an _extend_page_config_for_cpt
676
+		// then let's run that to modify all the various page configuration arrays.
677
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
678
+			$this->_extend_page_config_for_cpt();
679
+		}
680
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
681
+		$this->_page_routes = apply_filters(
682
+			'FHEE__' . $this->class_name . '__page_setup__page_routes',
683
+			$this->_page_routes,
684
+			$this
685
+		);
686
+		$this->_page_config = apply_filters(
687
+			'FHEE__' . $this->class_name . '__page_setup__page_config',
688
+			$this->_page_config,
689
+			$this
690
+		);
691
+		if ($this->base_class_name !== '') {
692
+			$this->_page_routes = apply_filters(
693
+				'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
694
+				$this->_page_routes,
695
+				$this
696
+			);
697
+			$this->_page_config = apply_filters(
698
+				'FHEE__' . $this->base_class_name . '__page_setup__page_config',
699
+				$this->_page_config,
700
+				$this
701
+			);
702
+		}
703
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
706
+			add_action(
707
+				'AHEE__EE_Admin_Page__route_admin_request',
708
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
709
+				10,
710
+				2
711
+			);
712
+		}
713
+		// next route only if routing enabled
714
+		if ($this->_routing && ! $this->request->isAjax()) {
715
+			$this->_verify_routes();
716
+			// next let's just check user_access and kill if no access
717
+			$this->check_user_access();
718
+			if ($this->_is_UI_request) {
719
+				// admin_init stuff - global, all views for this page class, specific view
720
+				add_action('admin_init', [$this, 'admin_init'], 10);
721
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
723
+				}
724
+			} else {
725
+				// hijack regular WP loading and route admin request immediately
726
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
727
+				$this->route_admin_request();
728
+			}
729
+		}
730
+	}
731
+
732
+
733
+	/**
734
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
735
+	 *
736
+	 * @return void
737
+	 * @throws EE_Error
738
+	 */
739
+	private function _do_other_page_hooks()
740
+	{
741
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
742
+		foreach ($registered_pages as $page) {
743
+			// now let's setup the file name and class that should be present
744
+			$classname = str_replace('.class.php', '', $page);
745
+			// autoloaders should take care of loading file
746
+			if (! class_exists($classname)) {
747
+				$error_msg[] = sprintf(
748
+					esc_html__(
749
+						'Something went wrong with loading the %s admin hooks page.',
750
+						'event_espresso'
751
+					),
752
+					$page
753
+				);
754
+				$error_msg[] = $error_msg[0]
755
+							   . "\r\n"
756
+							   . sprintf(
757
+								   esc_html__(
758
+									   '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',
759
+									   'event_espresso'
760
+								   ),
761
+								   $page,
762
+								   '<br />',
763
+								   '<strong>' . $classname . '</strong>'
764
+							   );
765
+				throw new EE_Error(implode('||', $error_msg));
766
+			}
767
+			// notice we are passing the instance of this class to the hook object.
768
+			$this->loader->getShared($classname, [$this]);
769
+		}
770
+	}
771
+
772
+
773
+	/**
774
+	 * @throws ReflectionException
775
+	 * @throws EE_Error
776
+	 */
777
+	public function load_page_dependencies()
778
+	{
779
+		try {
780
+			$this->_load_page_dependencies();
781
+		} catch (EE_Error $e) {
782
+			$e->get_error();
783
+		}
784
+	}
785
+
786
+
787
+	/**
788
+	 * load_page_dependencies
789
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
790
+	 *
791
+	 * @return void
792
+	 * @throws DomainException
793
+	 * @throws EE_Error
794
+	 * @throws InvalidArgumentException
795
+	 * @throws InvalidDataTypeException
796
+	 * @throws InvalidInterfaceException
797
+	 */
798
+	protected function _load_page_dependencies()
799
+	{
800
+		// let's set the current_screen and screen options to override what WP set
801
+		$this->_current_screen = get_current_screen();
802
+		// load admin_notices - global, page class, and view specific
803
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804
+		add_action('admin_notices', [$this, 'admin_notices'], 10);
805
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
807
+		}
808
+		// load network admin_notices - global, page class, and view specific
809
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
812
+		}
813
+		// this will save any per_page screen options if they are present
814
+		$this->_set_per_page_screen_options();
815
+		// setup list table properties
816
+		$this->_set_list_table();
817
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
818
+		// However in some cases the metaboxes will need to be added within a route handling callback.
819
+		$this->_add_registered_meta_boxes();
820
+		$this->_add_screen_columns();
821
+		// add screen options - global, page child class, and view specific
822
+		$this->_add_global_screen_options();
823
+		$this->_add_screen_options();
824
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
825
+		if (method_exists($this, $add_screen_options)) {
826
+			$this->{$add_screen_options}();
827
+		}
828
+		// add help tab(s) - set via page_config and qtips.
829
+		$this->_add_help_tabs();
830
+		$this->_add_qtips();
831
+		// add feature_pointers - global, page child class, and view specific
832
+		$this->_add_feature_pointers();
833
+		$this->_add_global_feature_pointers();
834
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
835
+		if (method_exists($this, $add_feature_pointer)) {
836
+			$this->{$add_feature_pointer}();
837
+		}
838
+		// enqueue scripts/styles - global, page class, and view specific
839
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
840
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
841
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
842
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
843
+		}
844
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
845
+		// admin_print_footer_scripts - global, page child class, and view specific.
846
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
847
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
848
+		// is a good use case. Notice the late priority we're giving these
849
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
850
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
851
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
852
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
853
+		}
854
+		// admin footer scripts
855
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
856
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
857
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
858
+			add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
859
+		}
860
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
861
+		// targeted hook
862
+		do_action(
863
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
864
+		);
865
+	}
866
+
867
+
868
+	/**
869
+	 * _set_defaults
870
+	 * This sets some global defaults for class properties.
871
+	 */
872
+	private function _set_defaults()
873
+	{
874
+		$this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
875
+		$this->_event                = $this->_template_path = $this->_column_template_path = null;
876
+		$this->_nav_tabs             = $this->_views = $this->_page_routes = [];
877
+		$this->_page_config          = $this->_default_route_query_args = [];
878
+		$this->_default_nav_tab_name = 'overview';
879
+		// init template args
880
+		$this->_template_args = [
881
+			'admin_page_header'  => '',
882
+			'admin_page_content' => '',
883
+			'post_body_content'  => '',
884
+			'before_list_table'  => '',
885
+			'after_list_table'   => '',
886
+		];
887
+	}
888
+
889
+
890
+	/**
891
+	 * route_admin_request
892
+	 *
893
+	 * @return void
894
+	 * @throws InvalidArgumentException
895
+	 * @throws InvalidInterfaceException
896
+	 * @throws InvalidDataTypeException
897
+	 * @throws EE_Error
898
+	 * @throws ReflectionException
899
+	 * @see    _route_admin_request()
900
+	 */
901
+	public function route_admin_request()
902
+	{
903
+		try {
904
+			$this->_route_admin_request();
905
+		} catch (EE_Error $e) {
906
+			$e->get_error();
907
+		}
908
+	}
909
+
910
+
911
+	public function set_wp_page_slug($wp_page_slug)
912
+	{
913
+		$this->_wp_page_slug = $wp_page_slug;
914
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
915
+		if (is_network_admin()) {
916
+			$this->_wp_page_slug .= '-network';
917
+		}
918
+	}
919
+
920
+
921
+	/**
922
+	 * _verify_routes
923
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
924
+	 * we know if we need to drop out.
925
+	 *
926
+	 * @return bool
927
+	 * @throws EE_Error
928
+	 */
929
+	protected function _verify_routes()
930
+	{
931
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
+		if (! $this->_current_page && ! $this->request->isAjax()) {
933
+			return false;
934
+		}
935
+		$this->_route = false;
936
+		// check that the page_routes array is not empty
937
+		if (empty($this->_page_routes)) {
938
+			// user error msg
939
+			$error_msg = sprintf(
940
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
941
+				$this->_admin_page_title
942
+			);
943
+			// developer error msg
944
+			$error_msg .= '||' . $error_msg
945
+						  . esc_html__(
946
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947
+							  'event_espresso'
948
+						  );
949
+			throw new EE_Error($error_msg);
950
+		}
951
+		// and that the requested page route exists
952
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
954
+			$this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
955
+		} else {
956
+			// user error msg
957
+			$error_msg = sprintf(
958
+				esc_html__(
959
+					'The requested page route does not exist for the %s admin page.',
960
+					'event_espresso'
961
+				),
962
+				$this->_admin_page_title
963
+			);
964
+			// developer error msg
965
+			$error_msg .= '||' . $error_msg
966
+						  . sprintf(
967
+							  esc_html__(
968
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
969
+								  'event_espresso'
970
+							  ),
971
+							  $this->_req_action
972
+						  );
973
+			throw new EE_Error($error_msg);
974
+		}
975
+		// and that a default route exists
976
+		if (! array_key_exists('default', $this->_page_routes)) {
977
+			// user error msg
978
+			$error_msg = sprintf(
979
+				esc_html__(
980
+					'A default page route has not been set for the % admin page.',
981
+					'event_espresso'
982
+				),
983
+				$this->_admin_page_title
984
+			);
985
+			// developer error msg
986
+			$error_msg .= '||' . $error_msg
987
+						  . esc_html__(
988
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989
+							  'event_espresso'
990
+						  );
991
+			throw new EE_Error($error_msg);
992
+		}
993
+
994
+		// first lets' catch if the UI request has EVER been set.
995
+		if ($this->_is_UI_request === null) {
996
+			// lets set if this is a UI request or not.
997
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
998
+			// wait a minute... we might have a noheader in the route array
999
+			$this->_is_UI_request = ! (
1000
+				is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
1001
+			)
1002
+				? $this->_is_UI_request
1003
+				: false;
1004
+		}
1005
+		$this->_set_current_labels();
1006
+		return true;
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1012
+	 *
1013
+	 * @param string $route the route name we're verifying
1014
+	 * @return bool we'll throw an exception if this isn't a valid route.
1015
+	 * @throws EE_Error
1016
+	 */
1017
+	protected function _verify_route($route)
1018
+	{
1019
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
1020
+			return true;
1021
+		}
1022
+		// user error msg
1023
+		$error_msg = sprintf(
1024
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1025
+			$this->_admin_page_title
1026
+		);
1027
+		// developer error msg
1028
+		$error_msg .= '||' . $error_msg
1029
+					  . sprintf(
1030
+						  esc_html__(
1031
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1032
+							  'event_espresso'
1033
+						  ),
1034
+						  $route
1035
+					  );
1036
+		throw new EE_Error($error_msg);
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 * perform nonce verification
1042
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1043
+	 * using this method (and save retyping!)
1044
+	 *
1045
+	 * @param string $nonce     The nonce sent
1046
+	 * @param string $nonce_ref The nonce reference string (name0)
1047
+	 * @return void
1048
+	 * @throws EE_Error
1049
+	 * @throws InvalidArgumentException
1050
+	 * @throws InvalidDataTypeException
1051
+	 * @throws InvalidInterfaceException
1052
+	 */
1053
+	protected function _verify_nonce($nonce, $nonce_ref)
1054
+	{
1055
+		// verify nonce against expected value
1056
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
1057
+			// these are not the droids you are looking for !!!
1058
+			$msg = sprintf(
1059
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
1060
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1061
+				'</a>'
1062
+			);
1063
+			if (WP_DEBUG) {
1064
+				$msg .= "\n  ";
1065
+				$msg .= sprintf(
1066
+					esc_html__(
1067
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1068
+						'event_espresso'
1069
+					),
1070
+					__CLASS__
1071
+				);
1072
+			}
1073
+			if (! $this->request->isAjax()) {
1074
+				wp_die($msg);
1075
+			}
1076
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
+			$this->_return_json();
1078
+		}
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * _route_admin_request()
1084
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1085
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1086
+	 * in the page routes and then will try to load the corresponding method.
1087
+	 *
1088
+	 * @return void
1089
+	 * @throws EE_Error
1090
+	 * @throws InvalidArgumentException
1091
+	 * @throws InvalidDataTypeException
1092
+	 * @throws InvalidInterfaceException
1093
+	 * @throws ReflectionException
1094
+	 */
1095
+	protected function _route_admin_request()
1096
+	{
1097
+		if (! $this->_is_UI_request) {
1098
+			$this->_verify_routes();
1099
+		}
1100
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1101
+		if ($this->_req_action !== 'default' && $nonce_check) {
1102
+			// set nonce from post data
1103
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1104
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1105
+		}
1106
+		// set the nav_tabs array but ONLY if this is  UI_request
1107
+		if ($this->_is_UI_request) {
1108
+			$this->_set_nav_tabs();
1109
+		}
1110
+		// grab callback function
1111
+		$func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1112
+		// check if callback has args
1113
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1114
+		$error_msg = '';
1115
+		// action right before calling route
1116
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119
+		}
1120
+		// strip _wp_http_referer from the server REQUEST_URI
1121
+		// else it grows in length on every submission due to recursion,
1122
+		// ultimately causing a "Request-URI Too Large" error
1123
+		$request_uri = remove_query_arg(
1124
+			'_wp_http_referer',
1125
+			wp_unslash($this->request->getServerParam('REQUEST_URI'))
1126
+		);
1127
+		// set new value in both our Request object and the super global
1128
+		$this->request->setServerParam('REQUEST_URI', $request_uri, true);
1129
+		if (! empty($func)) {
1130
+			if (is_array($func)) {
1131
+				[$class, $method] = $func;
1132
+			} elseif (strpos($func, '::') !== false) {
1133
+				[$class, $method] = explode('::', $func);
1134
+			} else {
1135
+				$class  = $this;
1136
+				$method = $func;
1137
+			}
1138
+			if (! (is_object($class) && $class === $this)) {
1139
+				// send along this admin page object for access by addons.
1140
+				$args['admin_page_object'] = $this;
1141
+			}
1142
+			if (
1143
+				// is it a method on a class that doesn't work?
1144
+				(
1145
+					(
1146
+						method_exists($class, $method)
1147
+						&& call_user_func_array([$class, $method], $args) === false
1148
+					)
1149
+					&& (
1150
+						// is it a standalone function that doesn't work?
1151
+						function_exists($method)
1152
+						&& call_user_func_array(
1153
+							$func,
1154
+							array_merge(['admin_page_object' => $this], $args)
1155
+						) === false
1156
+					)
1157
+				)
1158
+				|| (
1159
+					// is it neither a class method NOR a standalone function?
1160
+					! method_exists($class, $method)
1161
+					&& ! function_exists($method)
1162
+				)
1163
+			) {
1164
+				// user error msg
1165
+				$error_msg = esc_html__(
1166
+					'An error occurred. The  requested page route could not be found.',
1167
+					'event_espresso'
1168
+				);
1169
+				// developer error msg
1170
+				$error_msg .= '||';
1171
+				$error_msg .= sprintf(
1172
+					esc_html__(
1173
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1174
+						'event_espresso'
1175
+					),
1176
+					$method
1177
+				);
1178
+			}
1179
+			if (! empty($error_msg)) {
1180
+				throw new EE_Error($error_msg);
1181
+			}
1182
+		}
1183
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1184
+		// then we need to reset the routing properties to the new route.
1185
+		// 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.
1186
+		if (
1187
+			$this->_is_UI_request === false
1188
+			&& is_array($this->_route)
1189
+			&& ! empty($this->_route['headers_sent_route'])
1190
+		) {
1191
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1192
+		}
1193
+	}
1194
+
1195
+
1196
+	/**
1197
+	 * This method just allows the resetting of page properties in the case where a no headers
1198
+	 * route redirects to a headers route in its route config.
1199
+	 *
1200
+	 * @param string $new_route New (non header) route to redirect to.
1201
+	 * @return   void
1202
+	 * @throws ReflectionException
1203
+	 * @throws InvalidArgumentException
1204
+	 * @throws InvalidInterfaceException
1205
+	 * @throws InvalidDataTypeException
1206
+	 * @throws EE_Error
1207
+	 * @since   4.3.0
1208
+	 */
1209
+	protected function _reset_routing_properties($new_route)
1210
+	{
1211
+		$this->_is_UI_request = true;
1212
+		// now we set the current route to whatever the headers_sent_route is set at
1213
+		$this->request->setRequestParam('action', $new_route);
1214
+		// rerun page setup
1215
+		$this->_page_setup();
1216
+	}
1217
+
1218
+
1219
+	/**
1220
+	 * _add_query_arg
1221
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1222
+	 *(internally just uses EEH_URL's function with the same name)
1223
+	 *
1224
+	 * @param array  $args
1225
+	 * @param string $url
1226
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1227
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1228
+	 *                                        Example usage: If the current page is:
1229
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1230
+	 *                                        &action=default&event_id=20&month_range=March%202015
1231
+	 *                                        &_wpnonce=5467821
1232
+	 *                                        and you call:
1233
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1234
+	 *                                        array(
1235
+	 *                                        'action' => 'resend_something',
1236
+	 *                                        'page=>espresso_registrations'
1237
+	 *                                        ),
1238
+	 *                                        $some_url,
1239
+	 *                                        true
1240
+	 *                                        );
1241
+	 *                                        It will produce a url in this structure:
1242
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1243
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1244
+	 *                                        month_range]=March%202015
1245
+	 * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1246
+	 * @return string
1247
+	 */
1248
+	public static function add_query_args_and_nonce(
1249
+		$args = [],
1250
+		$url = '',
1251
+		$sticky = false,
1252
+		$exclude_nonce = false
1253
+	) {
1254
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1255
+		if ($sticky) {
1256
+			/** @var RequestInterface $request */
1257
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1258
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1259
+			$request->unSetServerParam('_wp_http_referer', true);
1260
+			foreach ($request->requestParams() as $key => $value) {
1261
+				// do not add nonces
1262
+				if (strpos($key, 'nonce') !== false) {
1263
+					continue;
1264
+				}
1265
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1266
+			}
1267
+		}
1268
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * This returns a generated link that will load the related help tab.
1274
+	 *
1275
+	 * @param string $help_tab_id the id for the connected help tab
1276
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1277
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1278
+	 * @return string              generated link
1279
+	 * @uses EEH_Template::get_help_tab_link()
1280
+	 */
1281
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1282
+	{
1283
+		return EEH_Template::get_help_tab_link(
1284
+			$help_tab_id,
1285
+			$this->page_slug,
1286
+			$this->_req_action,
1287
+			$icon_style,
1288
+			$help_text
1289
+		);
1290
+	}
1291
+
1292
+
1293
+	/**
1294
+	 * _add_help_tabs
1295
+	 * Note child classes define their help tabs within the page_config array.
1296
+	 *
1297
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1298
+	 * @return void
1299
+	 * @throws DomainException
1300
+	 * @throws EE_Error
1301
+	 * @throws ReflectionException
1302
+	 */
1303
+	protected function _add_help_tabs()
1304
+	{
1305
+		if (isset($this->_page_config[ $this->_req_action ])) {
1306
+			$config = $this->_page_config[ $this->_req_action ];
1307
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1308
+			if (is_array($config) && isset($config['help_sidebar'])) {
1309
+				// check that the callback given is valid
1310
+				if (! method_exists($this, $config['help_sidebar'])) {
1311
+					throw new EE_Error(
1312
+						sprintf(
1313
+							esc_html__(
1314
+								'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',
1315
+								'event_espresso'
1316
+							),
1317
+							$config['help_sidebar'],
1318
+							$this->class_name
1319
+						)
1320
+					);
1321
+				}
1322
+				$content = apply_filters(
1323
+					'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1324
+					$this->{$config['help_sidebar']}()
1325
+				);
1326
+				$this->_current_screen->set_help_sidebar($content);
1327
+			}
1328
+			if (! isset($config['help_tabs'])) {
1329
+				return;
1330
+			} //no help tabs for this route
1331
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1332
+				// we're here so there ARE help tabs!
1333
+				// make sure we've got what we need
1334
+				if (! isset($cfg['title'])) {
1335
+					throw new EE_Error(
1336
+						esc_html__(
1337
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1338
+							'event_espresso'
1339
+						)
1340
+					);
1341
+				}
1342
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1343
+					throw new EE_Error(
1344
+						esc_html__(
1345
+							'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',
1346
+							'event_espresso'
1347
+						)
1348
+					);
1349
+				}
1350
+				// first priority goes to content.
1351
+				if (! empty($cfg['content'])) {
1352
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1353
+					// second priority goes to filename
1354
+				} elseif (! empty($cfg['filename'])) {
1355
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1356
+					// 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)
1357
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1358
+															 . basename($this->_get_dir())
1359
+															 . '/help_tabs/'
1360
+															 . $cfg['filename']
1361
+															 . '.help_tab.php' : $file_path;
1362
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1363
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1364
+						EE_Error::add_error(
1365
+							sprintf(
1366
+								esc_html__(
1367
+									'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',
1368
+									'event_espresso'
1369
+								),
1370
+								$tab_id,
1371
+								key($config),
1372
+								$file_path
1373
+							),
1374
+							__FILE__,
1375
+							__FUNCTION__,
1376
+							__LINE__
1377
+						);
1378
+						return;
1379
+					}
1380
+					$template_args['admin_page_obj'] = $this;
1381
+					$content                         = EEH_Template::display_template(
1382
+						$file_path,
1383
+						$template_args,
1384
+						true
1385
+					);
1386
+				} else {
1387
+					$content = '';
1388
+				}
1389
+				// check if callback is valid
1390
+				if (
1391
+					empty($content)
1392
+					&& (
1393
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1394
+					)
1395
+				) {
1396
+					EE_Error::add_error(
1397
+						sprintf(
1398
+							esc_html__(
1399
+								'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.',
1400
+								'event_espresso'
1401
+							),
1402
+							$cfg['title']
1403
+						),
1404
+						__FILE__,
1405
+						__FUNCTION__,
1406
+						__LINE__
1407
+					);
1408
+					return;
1409
+				}
1410
+				// setup config array for help tab method
1411
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1412
+				$_ht = [
1413
+					'id'       => $id,
1414
+					'title'    => $cfg['title'],
1415
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1416
+					'content'  => $content,
1417
+				];
1418
+				$this->_current_screen->add_help_tab($_ht);
1419
+			}
1420
+		}
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * This simply sets up any qtips that have been defined in the page config
1426
+	 *
1427
+	 * @return void
1428
+	 * @throws ReflectionException
1429
+	 * @throws EE_Error
1430
+	 */
1431
+	protected function _add_qtips()
1432
+	{
1433
+		if (isset($this->_route_config['qtips'])) {
1434
+			$qtips = (array) $this->_route_config['qtips'];
1435
+			// load qtip loader
1436
+			$path = [
1437
+				$this->_get_dir() . '/qtips/',
1438
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1439
+			];
1440
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1441
+		}
1442
+	}
1443
+
1444
+
1445
+	/**
1446
+	 * _set_nav_tabs
1447
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1448
+	 * wish to add additional tabs or modify accordingly.
1449
+	 *
1450
+	 * @return void
1451
+	 * @throws InvalidArgumentException
1452
+	 * @throws InvalidInterfaceException
1453
+	 * @throws InvalidDataTypeException
1454
+	 */
1455
+	protected function _set_nav_tabs()
1456
+	{
1457
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1458
+		$i = 0;
1459
+		foreach ($this->_page_config as $slug => $config) {
1460
+			if (! is_array($config) || empty($config['nav'])) {
1461
+				continue;
1462
+			}
1463
+			// no nav tab for this config
1464
+			// check for persistent flag
1465
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1466
+				// nav tab is only to appear when route requested.
1467
+				continue;
1468
+			}
1469
+			if (! $this->check_user_access($slug, true)) {
1470
+				// no nav tab because current user does not have access.
1471
+				continue;
1472
+			}
1473
+			$css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1474
+			$this->_nav_tabs[ $slug ] = [
1475
+				'url'       => isset($config['nav']['url'])
1476
+					? $config['nav']['url']
1477
+					: EE_Admin_Page::add_query_args_and_nonce(
1478
+						['action' => $slug],
1479
+						$this->_admin_base_url
1480
+					),
1481
+				'link_text' => isset($config['nav']['label'])
1482
+					? $config['nav']['label']
1483
+					: ucwords(
1484
+						str_replace('_', ' ', $slug)
1485
+					),
1486
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1487
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1488
+			];
1489
+			$i++;
1490
+		}
1491
+		// if $this->_nav_tabs is empty then lets set the default
1492
+		if (empty($this->_nav_tabs)) {
1493
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1494
+				'url'       => $this->_admin_base_url,
1495
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1496
+				'css_class' => 'nav-tab-active',
1497
+				'order'     => 10,
1498
+			];
1499
+		}
1500
+		// now let's sort the tabs according to order
1501
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * _set_current_labels
1507
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1508
+	 * property array
1509
+	 *
1510
+	 * @return void
1511
+	 */
1512
+	private function _set_current_labels()
1513
+	{
1514
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1515
+			foreach ($this->_route_config['labels'] as $label => $text) {
1516
+				if (is_array($text)) {
1517
+					foreach ($text as $sublabel => $subtext) {
1518
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1519
+					}
1520
+				} else {
1521
+					$this->_labels[ $label ] = $text;
1522
+				}
1523
+			}
1524
+		}
1525
+	}
1526
+
1527
+
1528
+	/**
1529
+	 *        verifies user access for this admin page
1530
+	 *
1531
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1532
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1533
+	 *                               return false if verify fail.
1534
+	 * @return bool
1535
+	 * @throws InvalidArgumentException
1536
+	 * @throws InvalidDataTypeException
1537
+	 * @throws InvalidInterfaceException
1538
+	 */
1539
+	public function check_user_access($route_to_check = '', $verify_only = false)
1540
+	{
1541
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1542
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1543
+		$capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1544
+						  && is_array(
1545
+							  $this->_page_routes[ $route_to_check ]
1546
+						  )
1547
+						  && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1548
+			? $this->_page_routes[ $route_to_check ]['capability'] : null;
1549
+		if (empty($capability) && empty($route_to_check)) {
1550
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1551
+				: $this->_route['capability'];
1552
+		} else {
1553
+			$capability = empty($capability) ? 'manage_options' : $capability;
1554
+		}
1555
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1556
+		if (
1557
+			! $this->request->isAjax()
1558
+			&& (
1559
+				! function_exists('is_admin')
1560
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1561
+					$capability,
1562
+					$this->page_slug
1563
+					. '_'
1564
+					. $route_to_check,
1565
+					$id
1566
+				)
1567
+			)
1568
+		) {
1569
+			if ($verify_only) {
1570
+				return false;
1571
+			}
1572
+			if (is_user_logged_in()) {
1573
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1574
+			} else {
1575
+				return false;
1576
+			}
1577
+		}
1578
+		return true;
1579
+	}
1580
+
1581
+
1582
+	/**
1583
+	 * @param string                 $box_id
1584
+	 * @param string                 $title
1585
+	 * @param callable|string|null   $callback
1586
+	 * @param string|array|WP_Screen $screen
1587
+	 * @param string                 $context
1588
+	 * @param string                 $priority
1589
+	 * @param array|null             $callback_args
1590
+	 */
1591
+	protected function addMetaBox(
1592
+		string $box_id,
1593
+		string $title,
1594
+		$callback,
1595
+		$screen,
1596
+		string $context = 'normal',
1597
+		string $priority = 'default',
1598
+		?array $callback_args = null
1599
+	) {
1600
+		if (! is_callable($callback)) {
1601
+			return;
1602
+		}
1603
+
1604
+		add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1605
+		add_filter(
1606
+			"postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1607
+			function ($classes) {
1608
+				array_push($classes, 'ee-admin-container');
1609
+				return $classes;
1610
+			}
1611
+		);
1612
+	}
1613
+
1614
+
1615
+	/**
1616
+	 * admin_init_global
1617
+	 * This runs all the code that we want executed within the WP admin_init hook.
1618
+	 * This method executes for ALL EE Admin pages.
1619
+	 *
1620
+	 * @return void
1621
+	 */
1622
+	public function admin_init_global()
1623
+	{
1624
+	}
1625
+
1626
+
1627
+	/**
1628
+	 * wp_loaded_global
1629
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1630
+	 * EE_Admin page and will execute on every EE Admin Page load
1631
+	 *
1632
+	 * @return void
1633
+	 */
1634
+	public function wp_loaded()
1635
+	{
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 * admin_notices
1641
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1642
+	 * ALL EE_Admin pages.
1643
+	 *
1644
+	 * @return void
1645
+	 */
1646
+	public function admin_notices_global()
1647
+	{
1648
+		$this->_display_no_javascript_warning();
1649
+		$this->_display_espresso_notices();
1650
+	}
1651
+
1652
+
1653
+	public function network_admin_notices_global()
1654
+	{
1655
+		$this->_display_no_javascript_warning();
1656
+		$this->_display_espresso_notices();
1657
+	}
1658
+
1659
+
1660
+	/**
1661
+	 * admin_footer_scripts_global
1662
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1663
+	 * will apply on ALL EE_Admin pages.
1664
+	 *
1665
+	 * @return void
1666
+	 */
1667
+	public function admin_footer_scripts_global()
1668
+	{
1669
+		$this->_add_admin_page_ajax_loading_img();
1670
+		$this->_add_admin_page_overlay();
1671
+		// if metaboxes are present we need to add the nonce field
1672
+		if (
1673
+			isset($this->_route_config['metaboxes'])
1674
+			|| isset($this->_route_config['list_table'])
1675
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1676
+		) {
1677
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1678
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1679
+		}
1680
+	}
1681
+
1682
+
1683
+	/**
1684
+	 * admin_footer_global
1685
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1686
+	 * This particular method will apply on ALL EE_Admin Pages.
1687
+	 *
1688
+	 * @return void
1689
+	 */
1690
+	public function admin_footer_global()
1691
+	{
1692
+		// dialog container for dialog helper
1693
+		echo '
1694 1694
         <div class="ee-admin-dialog-container auto-hide hidden">
1695 1695
             <div class="ee-notices"></div>
1696 1696
             <div class="ee-admin-dialog-container-inner-content"></div>
1697 1697
         </div>
1698 1698
         ';
1699 1699
 
1700
-        // current set timezone for timezone js
1701
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1702
-    }
1703
-
1704
-
1705
-    /**
1706
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1707
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1708
-     * help popups then in your templates or your content you set "triggers" for the content using the
1709
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1710
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1711
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1712
-     * for the
1713
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1714
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1715
-     *    'help_trigger_id' => array(
1716
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1717
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1718
-     *    )
1719
-     * );
1720
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1721
-     *
1722
-     * @param array $help_array
1723
-     * @param bool  $display
1724
-     * @return string content
1725
-     * @throws DomainException
1726
-     * @throws EE_Error
1727
-     */
1728
-    protected function _set_help_popup_content($help_array = [], $display = false)
1729
-    {
1730
-        $content    = '';
1731
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1732
-        // loop through the array and setup content
1733
-        foreach ($help_array as $trigger => $help) {
1734
-            // make sure the array is setup properly
1735
-            if (! isset($help['title'], $help['content'])) {
1736
-                throw new EE_Error(
1737
-                    esc_html__(
1738
-                        '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',
1739
-                        'event_espresso'
1740
-                    )
1741
-                );
1742
-            }
1743
-            // we're good so let's setup the template vars and then assign parsed template content to our content.
1744
-            $template_args = [
1745
-                'help_popup_id'      => $trigger,
1746
-                'help_popup_title'   => $help['title'],
1747
-                'help_popup_content' => $help['content'],
1748
-            ];
1749
-            $content       .= EEH_Template::display_template(
1750
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1751
-                $template_args,
1752
-                true
1753
-            );
1754
-        }
1755
-        if ($display) {
1756
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1757
-            return '';
1758
-        }
1759
-        return $content;
1760
-    }
1761
-
1762
-
1763
-    /**
1764
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1765
-     *
1766
-     * @return array properly formatted array for help popup content
1767
-     * @throws EE_Error
1768
-     */
1769
-    private function _get_help_content()
1770
-    {
1771
-        // what is the method we're looking for?
1772
-        $method_name = '_help_popup_content_' . $this->_req_action;
1773
-        // if method doesn't exist let's get out.
1774
-        if (! method_exists($this, $method_name)) {
1775
-            return [];
1776
-        }
1777
-        // k we're good to go let's retrieve the help array
1778
-        $help_array = $this->{$method_name}();
1779
-        // make sure we've got an array!
1780
-        if (! is_array($help_array)) {
1781
-            throw new EE_Error(
1782
-                esc_html__(
1783
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1784
-                    'event_espresso'
1785
-                )
1786
-            );
1787
-        }
1788
-        return $help_array;
1789
-    }
1790
-
1791
-
1792
-    /**
1793
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1794
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1795
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1796
-     *
1797
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1798
-     * @param boolean $display    if false then we return the trigger string
1799
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1800
-     * @return string
1801
-     * @throws DomainException
1802
-     * @throws EE_Error
1803
-     */
1804
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1805
-    {
1806
-        if ($this->request->isAjax()) {
1807
-            return '';
1808
-        }
1809
-        // 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
1810
-        $help_array   = $this->_get_help_content();
1811
-        $help_content = '';
1812
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1813
-            $help_array[ $trigger_id ] = [
1814
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1815
-                'content' => esc_html__(
1816
-                    '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.)',
1817
-                    'event_espresso'
1818
-                ),
1819
-            ];
1820
-            $help_content = $this->_set_help_popup_content($help_array);
1821
-        }
1822
-        // let's setup the trigger
1823
-        $content = '<a class="ee-dialog" href="?height='
1824
-                   . esc_attr($dimensions[0])
1825
-                   . '&width='
1826
-                   . esc_attr($dimensions[1])
1827
-                   . '&inlineId='
1828
-                   . esc_attr($trigger_id)
1829
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1830
-        $content .= $help_content;
1831
-        if ($display) {
1832
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1833
-            return '';
1834
-        }
1835
-        return $content;
1836
-    }
1837
-
1838
-
1839
-    /**
1840
-     * _add_global_screen_options
1841
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1842
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1843
-     *
1844
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1845
-     *         see also WP_Screen object documents...
1846
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1847
-     * @abstract
1848
-     * @return void
1849
-     */
1850
-    private function _add_global_screen_options()
1851
-    {
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * _add_global_feature_pointers
1857
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1858
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1859
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1860
-     *
1861
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1862
-     *         extended) also see:
1863
-     * @link   http://eamann.com/tech/wordpress-portland/
1864
-     * @abstract
1865
-     * @return void
1866
-     */
1867
-    private function _add_global_feature_pointers()
1868
-    {
1869
-    }
1870
-
1871
-
1872
-    /**
1873
-     * load_global_scripts_styles
1874
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1875
-     *
1876
-     * @return void
1877
-     */
1878
-    public function load_global_scripts_styles()
1879
-    {
1880
-        // add debugging styles
1881
-        if (WP_DEBUG) {
1882
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1883
-        }
1884
-        // taking care of metaboxes
1885
-        if (
1886
-            empty($this->_cpt_route)
1887
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1888
-        ) {
1889
-            wp_enqueue_script('dashboard');
1890
-        }
1891
-
1892
-        wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1893
-        wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1894
-        // LOCALIZED DATA
1895
-        // localize script for ajax lazy loading
1896
-        wp_localize_script(
1897
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1898
-            'eeLazyLoadingContainers',
1899
-            apply_filters(
1900
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1901
-                ['espresso_news_post_box_content']
1902
-            )
1903
-        );
1904
-        StatusChangeNotice::loadAssets();
1905
-
1906
-        add_filter(
1907
-            'admin_body_class',
1908
-            function ($classes) {
1909
-                if (strpos($classes, 'espresso-admin') === false) {
1910
-                    $classes .= ' espresso-admin';
1911
-                }
1912
-                return $classes;
1913
-            }
1914
-        );
1915
-    }
1916
-
1917
-
1918
-    /**
1919
-     *        admin_footer_scripts_eei18n_js_strings
1920
-     *
1921
-     * @return        void
1922
-     */
1923
-    public function admin_footer_scripts_eei18n_js_strings()
1924
-    {
1925
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1926
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1927
-            __(
1928
-                '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!!!',
1929
-                'event_espresso'
1930
-            )
1931
-        );
1932
-        EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1933
-        EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1934
-        EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1935
-        EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1936
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1937
-        EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1938
-        EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1939
-        EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1940
-        EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1941
-        EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1942
-        EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1943
-        EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1944
-        EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1945
-        EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1946
-        EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1947
-        EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1948
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1949
-        EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1950
-        EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1951
-        EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1952
-        EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1953
-        EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1954
-        EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1955
-        EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1956
-        EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1957
-        EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1958
-        EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1959
-        EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1960
-        EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1961
-        EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1962
-        EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1963
-        EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1964
-        EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1965
-        EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1966
-        EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1967
-        EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1968
-        EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1969
-        EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1970
-    }
1971
-
1972
-
1973
-    /**
1974
-     *        load enhanced xdebug styles for ppl with failing eyesight
1975
-     *
1976
-     * @return        void
1977
-     */
1978
-    public function add_xdebug_style()
1979
-    {
1980
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1981
-    }
1982
-
1983
-
1984
-    /************************/
1985
-    /** LIST TABLE METHODS **/
1986
-    /************************/
1987
-    /**
1988
-     * this sets up the list table if the current view requires it.
1989
-     *
1990
-     * @return void
1991
-     * @throws EE_Error
1992
-     * @throws InvalidArgumentException
1993
-     * @throws InvalidDataTypeException
1994
-     * @throws InvalidInterfaceException
1995
-     */
1996
-    protected function _set_list_table()
1997
-    {
1998
-        // first is this a list_table view?
1999
-        if (! isset($this->_route_config['list_table'])) {
2000
-            return;
2001
-        } //not a list_table view so get out.
2002
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2003
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2004
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2005
-            // user error msg
2006
-            $error_msg = esc_html__(
2007
-                'An error occurred. The requested list table views could not be found.',
2008
-                'event_espresso'
2009
-            );
2010
-            // developer error msg
2011
-            $error_msg .= '||'
2012
-                          . sprintf(
2013
-                              esc_html__(
2014
-                                  '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.',
2015
-                                  'event_espresso'
2016
-                              ),
2017
-                              $this->_req_action,
2018
-                              $list_table_view
2019
-                          );
2020
-            throw new EE_Error($error_msg);
2021
-        }
2022
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2023
-        $this->_views = apply_filters(
2024
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2025
-            $this->_views
2026
-        );
2027
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2028
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2029
-        $this->_set_list_table_view();
2030
-        $this->_set_list_table_object();
2031
-    }
2032
-
2033
-
2034
-    /**
2035
-     * set current view for List Table
2036
-     *
2037
-     * @return void
2038
-     */
2039
-    protected function _set_list_table_view()
2040
-    {
2041
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2042
-        $status = $this->request->getRequestParam('status', null, 'key');
2043
-        $this->_view = $status && array_key_exists($status, $this->_views)
2044
-            ? $status
2045
-            : $this->_view;
2046
-    }
2047
-
2048
-
2049
-    /**
2050
-     * _set_list_table_object
2051
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2052
-     *
2053
-     * @throws InvalidInterfaceException
2054
-     * @throws InvalidArgumentException
2055
-     * @throws InvalidDataTypeException
2056
-     * @throws EE_Error
2057
-     * @throws InvalidInterfaceException
2058
-     */
2059
-    protected function _set_list_table_object()
2060
-    {
2061
-        if (isset($this->_route_config['list_table'])) {
2062
-            if (! class_exists($this->_route_config['list_table'])) {
2063
-                throw new EE_Error(
2064
-                    sprintf(
2065
-                        esc_html__(
2066
-                            '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.',
2067
-                            'event_espresso'
2068
-                        ),
2069
-                        $this->_route_config['list_table'],
2070
-                        $this->class_name
2071
-                    )
2072
-                );
2073
-            }
2074
-            $this->_list_table_object = $this->loader->getShared(
2075
-                $this->_route_config['list_table'],
2076
-                [$this]
2077
-            );
2078
-        }
2079
-    }
2080
-
2081
-
2082
-    /**
2083
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2084
-     *
2085
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2086
-     *                                                    urls.  The array should be indexed by the view it is being
2087
-     *                                                    added to.
2088
-     * @return array
2089
-     */
2090
-    public function get_list_table_view_RLs($extra_query_args = [])
2091
-    {
2092
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2093
-        if (empty($this->_views)) {
2094
-            $this->_views = [];
2095
-        }
2096
-        // cycle thru views
2097
-        foreach ($this->_views as $key => $view) {
2098
-            $query_args = [];
2099
-            // check for current view
2100
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2101
-            $query_args['action']                        = $this->_req_action;
2102
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2103
-            $query_args['status']                        = $view['slug'];
2104
-            // merge any other arguments sent in.
2105
-            if (isset($extra_query_args[ $view['slug'] ])) {
2106
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2107
-                    $query_args[] = $extra_query_arg;
2108
-                }
2109
-            }
2110
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2111
-        }
2112
-        return $this->_views;
2113
-    }
2114
-
2115
-
2116
-    /**
2117
-     * _entries_per_page_dropdown
2118
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2119
-     *
2120
-     * @param int $max_entries total number of rows in the table
2121
-     * @return string
2122
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2123
-     *         WP does it.
2124
-     */
2125
-    protected function _entries_per_page_dropdown($max_entries = 0)
2126
-    {
2127
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2128
-        $values   = [10, 25, 50, 100];
2129
-        $per_page = $this->request->getRequestParam('per_page', 10, 'int');
2130
-        if ($max_entries) {
2131
-            $values[] = $max_entries;
2132
-            sort($values);
2133
-        }
2134
-        $entries_per_page_dropdown = '
1700
+		// current set timezone for timezone js
1701
+		echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1702
+	}
1703
+
1704
+
1705
+	/**
1706
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1707
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1708
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1709
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1710
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1711
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1712
+	 * for the
1713
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1714
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1715
+	 *    'help_trigger_id' => array(
1716
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1717
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1718
+	 *    )
1719
+	 * );
1720
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1721
+	 *
1722
+	 * @param array $help_array
1723
+	 * @param bool  $display
1724
+	 * @return string content
1725
+	 * @throws DomainException
1726
+	 * @throws EE_Error
1727
+	 */
1728
+	protected function _set_help_popup_content($help_array = [], $display = false)
1729
+	{
1730
+		$content    = '';
1731
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1732
+		// loop through the array and setup content
1733
+		foreach ($help_array as $trigger => $help) {
1734
+			// make sure the array is setup properly
1735
+			if (! isset($help['title'], $help['content'])) {
1736
+				throw new EE_Error(
1737
+					esc_html__(
1738
+						'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',
1739
+						'event_espresso'
1740
+					)
1741
+				);
1742
+			}
1743
+			// we're good so let's setup the template vars and then assign parsed template content to our content.
1744
+			$template_args = [
1745
+				'help_popup_id'      => $trigger,
1746
+				'help_popup_title'   => $help['title'],
1747
+				'help_popup_content' => $help['content'],
1748
+			];
1749
+			$content       .= EEH_Template::display_template(
1750
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1751
+				$template_args,
1752
+				true
1753
+			);
1754
+		}
1755
+		if ($display) {
1756
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1757
+			return '';
1758
+		}
1759
+		return $content;
1760
+	}
1761
+
1762
+
1763
+	/**
1764
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1765
+	 *
1766
+	 * @return array properly formatted array for help popup content
1767
+	 * @throws EE_Error
1768
+	 */
1769
+	private function _get_help_content()
1770
+	{
1771
+		// what is the method we're looking for?
1772
+		$method_name = '_help_popup_content_' . $this->_req_action;
1773
+		// if method doesn't exist let's get out.
1774
+		if (! method_exists($this, $method_name)) {
1775
+			return [];
1776
+		}
1777
+		// k we're good to go let's retrieve the help array
1778
+		$help_array = $this->{$method_name}();
1779
+		// make sure we've got an array!
1780
+		if (! is_array($help_array)) {
1781
+			throw new EE_Error(
1782
+				esc_html__(
1783
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1784
+					'event_espresso'
1785
+				)
1786
+			);
1787
+		}
1788
+		return $help_array;
1789
+	}
1790
+
1791
+
1792
+	/**
1793
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1794
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1795
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1796
+	 *
1797
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1798
+	 * @param boolean $display    if false then we return the trigger string
1799
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1800
+	 * @return string
1801
+	 * @throws DomainException
1802
+	 * @throws EE_Error
1803
+	 */
1804
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1805
+	{
1806
+		if ($this->request->isAjax()) {
1807
+			return '';
1808
+		}
1809
+		// 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
1810
+		$help_array   = $this->_get_help_content();
1811
+		$help_content = '';
1812
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1813
+			$help_array[ $trigger_id ] = [
1814
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1815
+				'content' => esc_html__(
1816
+					'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.)',
1817
+					'event_espresso'
1818
+				),
1819
+			];
1820
+			$help_content = $this->_set_help_popup_content($help_array);
1821
+		}
1822
+		// let's setup the trigger
1823
+		$content = '<a class="ee-dialog" href="?height='
1824
+				   . esc_attr($dimensions[0])
1825
+				   . '&width='
1826
+				   . esc_attr($dimensions[1])
1827
+				   . '&inlineId='
1828
+				   . esc_attr($trigger_id)
1829
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1830
+		$content .= $help_content;
1831
+		if ($display) {
1832
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1833
+			return '';
1834
+		}
1835
+		return $content;
1836
+	}
1837
+
1838
+
1839
+	/**
1840
+	 * _add_global_screen_options
1841
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1842
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1843
+	 *
1844
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1845
+	 *         see also WP_Screen object documents...
1846
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1847
+	 * @abstract
1848
+	 * @return void
1849
+	 */
1850
+	private function _add_global_screen_options()
1851
+	{
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * _add_global_feature_pointers
1857
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1858
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1859
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1860
+	 *
1861
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1862
+	 *         extended) also see:
1863
+	 * @link   http://eamann.com/tech/wordpress-portland/
1864
+	 * @abstract
1865
+	 * @return void
1866
+	 */
1867
+	private function _add_global_feature_pointers()
1868
+	{
1869
+	}
1870
+
1871
+
1872
+	/**
1873
+	 * load_global_scripts_styles
1874
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1875
+	 *
1876
+	 * @return void
1877
+	 */
1878
+	public function load_global_scripts_styles()
1879
+	{
1880
+		// add debugging styles
1881
+		if (WP_DEBUG) {
1882
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1883
+		}
1884
+		// taking care of metaboxes
1885
+		if (
1886
+			empty($this->_cpt_route)
1887
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1888
+		) {
1889
+			wp_enqueue_script('dashboard');
1890
+		}
1891
+
1892
+		wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1893
+		wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1894
+		// LOCALIZED DATA
1895
+		// localize script for ajax lazy loading
1896
+		wp_localize_script(
1897
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1898
+			'eeLazyLoadingContainers',
1899
+			apply_filters(
1900
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1901
+				['espresso_news_post_box_content']
1902
+			)
1903
+		);
1904
+		StatusChangeNotice::loadAssets();
1905
+
1906
+		add_filter(
1907
+			'admin_body_class',
1908
+			function ($classes) {
1909
+				if (strpos($classes, 'espresso-admin') === false) {
1910
+					$classes .= ' espresso-admin';
1911
+				}
1912
+				return $classes;
1913
+			}
1914
+		);
1915
+	}
1916
+
1917
+
1918
+	/**
1919
+	 *        admin_footer_scripts_eei18n_js_strings
1920
+	 *
1921
+	 * @return        void
1922
+	 */
1923
+	public function admin_footer_scripts_eei18n_js_strings()
1924
+	{
1925
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
1926
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1927
+			__(
1928
+				'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!!!',
1929
+				'event_espresso'
1930
+			)
1931
+		);
1932
+		EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
1933
+		EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
1934
+		EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
1935
+		EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
1936
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1937
+		EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
1938
+		EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
1939
+		EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
1940
+		EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
1941
+		EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
1942
+		EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
1943
+		EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
1944
+		EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
1945
+		EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
1946
+		EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
1947
+		EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
1948
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
1949
+		EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
1950
+		EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
1951
+		EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
1952
+		EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
1953
+		EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
1954
+		EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
1955
+		EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
1956
+		EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1957
+		EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
1958
+		EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1959
+		EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1960
+		EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1961
+		EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
1962
+		EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1963
+		EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
1964
+		EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
1965
+		EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
1966
+		EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
1967
+		EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
1968
+		EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
1969
+		EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
1970
+	}
1971
+
1972
+
1973
+	/**
1974
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1975
+	 *
1976
+	 * @return        void
1977
+	 */
1978
+	public function add_xdebug_style()
1979
+	{
1980
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1981
+	}
1982
+
1983
+
1984
+	/************************/
1985
+	/** LIST TABLE METHODS **/
1986
+	/************************/
1987
+	/**
1988
+	 * this sets up the list table if the current view requires it.
1989
+	 *
1990
+	 * @return void
1991
+	 * @throws EE_Error
1992
+	 * @throws InvalidArgumentException
1993
+	 * @throws InvalidDataTypeException
1994
+	 * @throws InvalidInterfaceException
1995
+	 */
1996
+	protected function _set_list_table()
1997
+	{
1998
+		// first is this a list_table view?
1999
+		if (! isset($this->_route_config['list_table'])) {
2000
+			return;
2001
+		} //not a list_table view so get out.
2002
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2003
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2004
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2005
+			// user error msg
2006
+			$error_msg = esc_html__(
2007
+				'An error occurred. The requested list table views could not be found.',
2008
+				'event_espresso'
2009
+			);
2010
+			// developer error msg
2011
+			$error_msg .= '||'
2012
+						  . sprintf(
2013
+							  esc_html__(
2014
+								  '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.',
2015
+								  'event_espresso'
2016
+							  ),
2017
+							  $this->_req_action,
2018
+							  $list_table_view
2019
+						  );
2020
+			throw new EE_Error($error_msg);
2021
+		}
2022
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2023
+		$this->_views = apply_filters(
2024
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2025
+			$this->_views
2026
+		);
2027
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2028
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2029
+		$this->_set_list_table_view();
2030
+		$this->_set_list_table_object();
2031
+	}
2032
+
2033
+
2034
+	/**
2035
+	 * set current view for List Table
2036
+	 *
2037
+	 * @return void
2038
+	 */
2039
+	protected function _set_list_table_view()
2040
+	{
2041
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2042
+		$status = $this->request->getRequestParam('status', null, 'key');
2043
+		$this->_view = $status && array_key_exists($status, $this->_views)
2044
+			? $status
2045
+			: $this->_view;
2046
+	}
2047
+
2048
+
2049
+	/**
2050
+	 * _set_list_table_object
2051
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2052
+	 *
2053
+	 * @throws InvalidInterfaceException
2054
+	 * @throws InvalidArgumentException
2055
+	 * @throws InvalidDataTypeException
2056
+	 * @throws EE_Error
2057
+	 * @throws InvalidInterfaceException
2058
+	 */
2059
+	protected function _set_list_table_object()
2060
+	{
2061
+		if (isset($this->_route_config['list_table'])) {
2062
+			if (! class_exists($this->_route_config['list_table'])) {
2063
+				throw new EE_Error(
2064
+					sprintf(
2065
+						esc_html__(
2066
+							'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.',
2067
+							'event_espresso'
2068
+						),
2069
+						$this->_route_config['list_table'],
2070
+						$this->class_name
2071
+					)
2072
+				);
2073
+			}
2074
+			$this->_list_table_object = $this->loader->getShared(
2075
+				$this->_route_config['list_table'],
2076
+				[$this]
2077
+			);
2078
+		}
2079
+	}
2080
+
2081
+
2082
+	/**
2083
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2084
+	 *
2085
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2086
+	 *                                                    urls.  The array should be indexed by the view it is being
2087
+	 *                                                    added to.
2088
+	 * @return array
2089
+	 */
2090
+	public function get_list_table_view_RLs($extra_query_args = [])
2091
+	{
2092
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2093
+		if (empty($this->_views)) {
2094
+			$this->_views = [];
2095
+		}
2096
+		// cycle thru views
2097
+		foreach ($this->_views as $key => $view) {
2098
+			$query_args = [];
2099
+			// check for current view
2100
+			$this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2101
+			$query_args['action']                        = $this->_req_action;
2102
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2103
+			$query_args['status']                        = $view['slug'];
2104
+			// merge any other arguments sent in.
2105
+			if (isset($extra_query_args[ $view['slug'] ])) {
2106
+				foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2107
+					$query_args[] = $extra_query_arg;
2108
+				}
2109
+			}
2110
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2111
+		}
2112
+		return $this->_views;
2113
+	}
2114
+
2115
+
2116
+	/**
2117
+	 * _entries_per_page_dropdown
2118
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2119
+	 *
2120
+	 * @param int $max_entries total number of rows in the table
2121
+	 * @return string
2122
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2123
+	 *         WP does it.
2124
+	 */
2125
+	protected function _entries_per_page_dropdown($max_entries = 0)
2126
+	{
2127
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2128
+		$values   = [10, 25, 50, 100];
2129
+		$per_page = $this->request->getRequestParam('per_page', 10, 'int');
2130
+		if ($max_entries) {
2131
+			$values[] = $max_entries;
2132
+			sort($values);
2133
+		}
2134
+		$entries_per_page_dropdown = '
2135 2135
 			<div id="entries-per-page-dv" class="alignleft actions">
2136 2136
 				<label class="hide-if-no-js">
2137 2137
 					Show
2138 2138
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2139
-        foreach ($values as $value) {
2140
-            if ($value < $max_entries) {
2141
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2142
-                $entries_per_page_dropdown .= '
2139
+		foreach ($values as $value) {
2140
+			if ($value < $max_entries) {
2141
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2142
+				$entries_per_page_dropdown .= '
2143 2143
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2144
-            }
2145
-        }
2146
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2147
-        $entries_per_page_dropdown .= '
2144
+			}
2145
+		}
2146
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2147
+		$entries_per_page_dropdown .= '
2148 2148
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2149
-        $entries_per_page_dropdown .= '
2149
+		$entries_per_page_dropdown .= '
2150 2150
 					</select>
2151 2151
 					entries
2152 2152
 				</label>
2153 2153
 				<input id="entries-per-page-btn" class="button button--secondary" type="submit" value="Go" >
2154 2154
 			</div>
2155 2155
 		';
2156
-        return $entries_per_page_dropdown;
2157
-    }
2158
-
2159
-
2160
-    /**
2161
-     *        _set_search_attributes
2162
-     *
2163
-     * @return        void
2164
-     */
2165
-    public function _set_search_attributes()
2166
-    {
2167
-        $this->_template_args['search']['btn_label'] = sprintf(
2168
-            esc_html__('Search %s', 'event_espresso'),
2169
-            empty($this->_search_btn_label) ? $this->page_label
2170
-                : $this->_search_btn_label
2171
-        );
2172
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2173
-    }
2174
-
2175
-
2176
-
2177
-    /*** END LIST TABLE METHODS **/
2178
-
2179
-
2180
-    /**
2181
-     * _add_registered_metaboxes
2182
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2183
-     *
2184
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2185
-     * @return void
2186
-     * @throws EE_Error
2187
-     */
2188
-    private function _add_registered_meta_boxes()
2189
-    {
2190
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2191
-        // we only add meta boxes if the page_route calls for it
2192
-        if (
2193
-            is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2194
-            && is_array(
2195
-                $this->_route_config['metaboxes']
2196
-            )
2197
-        ) {
2198
-            // this simply loops through the callbacks provided
2199
-            // and checks if there is a corresponding callback registered by the child
2200
-            // if there is then we go ahead and process the metabox loader.
2201
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2202
-                // first check for Closures
2203
-                if ($metabox_callback instanceof Closure) {
2204
-                    $result = $metabox_callback();
2205
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2206
-                    $result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2207
-                } else {
2208
-                    $result = $this->{$metabox_callback}();
2209
-                }
2210
-                if ($result === false) {
2211
-                    // user error msg
2212
-                    $error_msg = esc_html__(
2213
-                        'An error occurred. The  requested metabox could not be found.',
2214
-                        'event_espresso'
2215
-                    );
2216
-                    // developer error msg
2217
-                    $error_msg .= '||'
2218
-                                  . sprintf(
2219
-                                      esc_html__(
2220
-                                          '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.',
2221
-                                          'event_espresso'
2222
-                                      ),
2223
-                                      $metabox_callback
2224
-                                  );
2225
-                    throw new EE_Error($error_msg);
2226
-                }
2227
-            }
2228
-        }
2229
-    }
2230
-
2231
-
2232
-    /**
2233
-     * _add_screen_columns
2234
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2235
-     * the dynamic column template and we'll setup the column options for the page.
2236
-     *
2237
-     * @return void
2238
-     */
2239
-    private function _add_screen_columns()
2240
-    {
2241
-        if (
2242
-            is_array($this->_route_config)
2243
-            && isset($this->_route_config['columns'])
2244
-            && is_array($this->_route_config['columns'])
2245
-            && count($this->_route_config['columns']) === 2
2246
-        ) {
2247
-            add_screen_option(
2248
-                'layout_columns',
2249
-                [
2250
-                    'max'     => (int) $this->_route_config['columns'][0],
2251
-                    'default' => (int) $this->_route_config['columns'][1],
2252
-                ]
2253
-            );
2254
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2255
-            $screen_id                                           = $this->_current_screen->id;
2256
-            $screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2257
-            $total_columns                                       = ! empty($screen_columns)
2258
-                ? $screen_columns
2259
-                : $this->_route_config['columns'][1];
2260
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2261
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2262
-            $this->_template_args['screen']                      = $this->_current_screen;
2263
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2264
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2265
-            // finally if we don't have has_metaboxes set in the route config
2266
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2267
-            $this->_route_config['has_metaboxes'] = true;
2268
-        }
2269
-    }
2270
-
2271
-
2272
-
2273
-    /** GLOBALLY AVAILABLE METABOXES **/
2274
-
2275
-
2276
-    /**
2277
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2278
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2279
-     * these get loaded on.
2280
-     */
2281
-    private function _espresso_news_post_box()
2282
-    {
2283
-        $news_box_title = apply_filters(
2284
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2285
-            esc_html__('New @ Event Espresso', 'event_espresso')
2286
-        );
2287
-        $this->addMetaBox(
2288
-            'espresso_news_post_box',
2289
-            $news_box_title,
2290
-            [
2291
-                $this,
2292
-                'espresso_news_post_box',
2293
-            ],
2294
-            $this->_wp_page_slug,
2295
-            'side',
2296
-            'low'
2297
-        );
2298
-    }
2299
-
2300
-
2301
-    /**
2302
-     * Code for setting up espresso ratings request metabox.
2303
-     */
2304
-    protected function _espresso_ratings_request()
2305
-    {
2306
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2307
-            return;
2308
-        }
2309
-        $ratings_box_title = apply_filters(
2310
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2311
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2312
-        );
2313
-        $this->addMetaBox(
2314
-            'espresso_ratings_request',
2315
-            $ratings_box_title,
2316
-            [
2317
-                $this,
2318
-                'espresso_ratings_request',
2319
-            ],
2320
-            $this->_wp_page_slug,
2321
-            'side'
2322
-        );
2323
-    }
2324
-
2325
-
2326
-    /**
2327
-     * Code for setting up espresso ratings request metabox content.
2328
-     *
2329
-     * @throws DomainException
2330
-     */
2331
-    public function espresso_ratings_request()
2332
-    {
2333
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2334
-    }
2335
-
2336
-
2337
-    public static function cached_rss_display($rss_id, $url)
2338
-    {
2339
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2340
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2341
-                     . '</p><p class="hide-if-js">'
2342
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2343
-                     . '</p>';
2344
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2345
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2346
-        $post      = '</div>' . "\n";
2347
-        $cache_key = 'ee_rss_' . md5($rss_id);
2348
-        $output    = get_transient($cache_key);
2349
-        if ($output !== false) {
2350
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2351
-            return true;
2352
-        }
2353
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2355
-            return false;
2356
-        }
2357
-        ob_start();
2358
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2359
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2360
-        return true;
2361
-    }
2362
-
2363
-
2364
-    public function espresso_news_post_box()
2365
-    {
2366
-        ?>
2156
+		return $entries_per_page_dropdown;
2157
+	}
2158
+
2159
+
2160
+	/**
2161
+	 *        _set_search_attributes
2162
+	 *
2163
+	 * @return        void
2164
+	 */
2165
+	public function _set_search_attributes()
2166
+	{
2167
+		$this->_template_args['search']['btn_label'] = sprintf(
2168
+			esc_html__('Search %s', 'event_espresso'),
2169
+			empty($this->_search_btn_label) ? $this->page_label
2170
+				: $this->_search_btn_label
2171
+		);
2172
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2173
+	}
2174
+
2175
+
2176
+
2177
+	/*** END LIST TABLE METHODS **/
2178
+
2179
+
2180
+	/**
2181
+	 * _add_registered_metaboxes
2182
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2183
+	 *
2184
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2185
+	 * @return void
2186
+	 * @throws EE_Error
2187
+	 */
2188
+	private function _add_registered_meta_boxes()
2189
+	{
2190
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2191
+		// we only add meta boxes if the page_route calls for it
2192
+		if (
2193
+			is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2194
+			&& is_array(
2195
+				$this->_route_config['metaboxes']
2196
+			)
2197
+		) {
2198
+			// this simply loops through the callbacks provided
2199
+			// and checks if there is a corresponding callback registered by the child
2200
+			// if there is then we go ahead and process the metabox loader.
2201
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2202
+				// first check for Closures
2203
+				if ($metabox_callback instanceof Closure) {
2204
+					$result = $metabox_callback();
2205
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2206
+					$result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2207
+				} else {
2208
+					$result = $this->{$metabox_callback}();
2209
+				}
2210
+				if ($result === false) {
2211
+					// user error msg
2212
+					$error_msg = esc_html__(
2213
+						'An error occurred. The  requested metabox could not be found.',
2214
+						'event_espresso'
2215
+					);
2216
+					// developer error msg
2217
+					$error_msg .= '||'
2218
+								  . sprintf(
2219
+									  esc_html__(
2220
+										  '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.',
2221
+										  'event_espresso'
2222
+									  ),
2223
+									  $metabox_callback
2224
+								  );
2225
+					throw new EE_Error($error_msg);
2226
+				}
2227
+			}
2228
+		}
2229
+	}
2230
+
2231
+
2232
+	/**
2233
+	 * _add_screen_columns
2234
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2235
+	 * the dynamic column template and we'll setup the column options for the page.
2236
+	 *
2237
+	 * @return void
2238
+	 */
2239
+	private function _add_screen_columns()
2240
+	{
2241
+		if (
2242
+			is_array($this->_route_config)
2243
+			&& isset($this->_route_config['columns'])
2244
+			&& is_array($this->_route_config['columns'])
2245
+			&& count($this->_route_config['columns']) === 2
2246
+		) {
2247
+			add_screen_option(
2248
+				'layout_columns',
2249
+				[
2250
+					'max'     => (int) $this->_route_config['columns'][0],
2251
+					'default' => (int) $this->_route_config['columns'][1],
2252
+				]
2253
+			);
2254
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2255
+			$screen_id                                           = $this->_current_screen->id;
2256
+			$screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2257
+			$total_columns                                       = ! empty($screen_columns)
2258
+				? $screen_columns
2259
+				: $this->_route_config['columns'][1];
2260
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2261
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2262
+			$this->_template_args['screen']                      = $this->_current_screen;
2263
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2264
+																   . 'admin_details_metabox_column_wrapper.template.php';
2265
+			// finally if we don't have has_metaboxes set in the route config
2266
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2267
+			$this->_route_config['has_metaboxes'] = true;
2268
+		}
2269
+	}
2270
+
2271
+
2272
+
2273
+	/** GLOBALLY AVAILABLE METABOXES **/
2274
+
2275
+
2276
+	/**
2277
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2278
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2279
+	 * these get loaded on.
2280
+	 */
2281
+	private function _espresso_news_post_box()
2282
+	{
2283
+		$news_box_title = apply_filters(
2284
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2285
+			esc_html__('New @ Event Espresso', 'event_espresso')
2286
+		);
2287
+		$this->addMetaBox(
2288
+			'espresso_news_post_box',
2289
+			$news_box_title,
2290
+			[
2291
+				$this,
2292
+				'espresso_news_post_box',
2293
+			],
2294
+			$this->_wp_page_slug,
2295
+			'side',
2296
+			'low'
2297
+		);
2298
+	}
2299
+
2300
+
2301
+	/**
2302
+	 * Code for setting up espresso ratings request metabox.
2303
+	 */
2304
+	protected function _espresso_ratings_request()
2305
+	{
2306
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2307
+			return;
2308
+		}
2309
+		$ratings_box_title = apply_filters(
2310
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2311
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2312
+		);
2313
+		$this->addMetaBox(
2314
+			'espresso_ratings_request',
2315
+			$ratings_box_title,
2316
+			[
2317
+				$this,
2318
+				'espresso_ratings_request',
2319
+			],
2320
+			$this->_wp_page_slug,
2321
+			'side'
2322
+		);
2323
+	}
2324
+
2325
+
2326
+	/**
2327
+	 * Code for setting up espresso ratings request metabox content.
2328
+	 *
2329
+	 * @throws DomainException
2330
+	 */
2331
+	public function espresso_ratings_request()
2332
+	{
2333
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2334
+	}
2335
+
2336
+
2337
+	public static function cached_rss_display($rss_id, $url)
2338
+	{
2339
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2340
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2341
+					 . '</p><p class="hide-if-js">'
2342
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2343
+					 . '</p>';
2344
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2345
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2346
+		$post      = '</div>' . "\n";
2347
+		$cache_key = 'ee_rss_' . md5($rss_id);
2348
+		$output    = get_transient($cache_key);
2349
+		if ($output !== false) {
2350
+			echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2351
+			return true;
2352
+		}
2353
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
+			echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2355
+			return false;
2356
+		}
2357
+		ob_start();
2358
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2359
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2360
+		return true;
2361
+	}
2362
+
2363
+
2364
+	public function espresso_news_post_box()
2365
+	{
2366
+		?>
2367 2367
         <div class="padding">
2368 2368
             <div id="espresso_news_post_box_content" class="infolinks">
2369 2369
                 <?php
2370
-                // Get RSS Feed(s)
2371
-                EE_Admin_Page::cached_rss_display(
2372
-                    'espresso_news_post_box_content',
2373
-                    esc_url_raw(
2374
-                        apply_filters(
2375
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2376
-                            'https://eventespresso.com/feed/'
2377
-                        )
2378
-                    )
2379
-                );
2380
-                ?>
2370
+				// Get RSS Feed(s)
2371
+				EE_Admin_Page::cached_rss_display(
2372
+					'espresso_news_post_box_content',
2373
+					esc_url_raw(
2374
+						apply_filters(
2375
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2376
+							'https://eventespresso.com/feed/'
2377
+						)
2378
+					)
2379
+				);
2380
+				?>
2381 2381
             </div>
2382 2382
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2383 2383
         </div>
2384 2384
         <?php
2385
-    }
2386
-
2387
-
2388
-    private function _espresso_links_post_box()
2389
-    {
2390
-        // Hiding until we actually have content to put in here...
2391
-        // $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2392
-    }
2393
-
2394
-
2395
-    public function espresso_links_post_box()
2396
-    {
2397
-        // Hiding until we actually have content to put in here...
2398
-        // EEH_Template::display_template(
2399
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2400
-        // );
2401
-    }
2402
-
2403
-
2404
-    protected function _espresso_sponsors_post_box()
2405
-    {
2406
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2407
-            $this->addMetaBox(
2408
-                'espresso_sponsors_post_box',
2409
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2410
-                [$this, 'espresso_sponsors_post_box'],
2411
-                $this->_wp_page_slug,
2412
-                'side'
2413
-            );
2414
-        }
2415
-    }
2416
-
2417
-
2418
-    public function espresso_sponsors_post_box()
2419
-    {
2420
-        EEH_Template::display_template(
2421
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2422
-        );
2423
-    }
2424
-
2425
-
2426
-    private function _publish_post_box()
2427
-    {
2428
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2429
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2430
-        // then we'll use that for the metabox label.
2431
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2432
-        if (! empty($this->_labels['publishbox'])) {
2433
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2434
-                : $this->_labels['publishbox'];
2435
-        } else {
2436
-            $box_label = esc_html__('Publish', 'event_espresso');
2437
-        }
2438
-        $box_label = apply_filters(
2439
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2440
-            $box_label,
2441
-            $this->_req_action,
2442
-            $this
2443
-        );
2444
-        $this->addMetaBox(
2445
-            $meta_box_ref,
2446
-            $box_label,
2447
-            [$this, 'editor_overview'],
2448
-            $this->_current_screen->id,
2449
-            'side',
2450
-            'high'
2451
-        );
2452
-    }
2453
-
2454
-
2455
-    public function editor_overview()
2456
-    {
2457
-        // if we have extra content set let's add it in if not make sure its empty
2458
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2459
-            ? $this->_template_args['publish_box_extra_content']
2460
-            : '';
2461
-        echo EEH_Template::display_template(
2462
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2463
-            $this->_template_args,
2464
-            true
2465
-        );
2466
-    }
2467
-
2468
-
2469
-    /** end of globally available metaboxes section **/
2470
-
2471
-
2472
-    /**
2473
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2474
-     * protected method.
2475
-     *
2476
-     * @param string $name
2477
-     * @param int    $id
2478
-     * @param bool   $delete
2479
-     * @param string $save_close_redirect_URL
2480
-     * @param bool   $both_btns
2481
-     * @throws EE_Error
2482
-     * @throws InvalidArgumentException
2483
-     * @throws InvalidDataTypeException
2484
-     * @throws InvalidInterfaceException
2485
-     * @see   $this->_set_publish_post_box_vars for param details
2486
-     * @since 4.6.0
2487
-     */
2488
-    public function set_publish_post_box_vars(
2489
-        $name = '',
2490
-        $id = 0,
2491
-        $delete = false,
2492
-        $save_close_redirect_URL = '',
2493
-        $both_btns = true
2494
-    ) {
2495
-        $this->_set_publish_post_box_vars(
2496
-            $name,
2497
-            $id,
2498
-            $delete,
2499
-            $save_close_redirect_URL,
2500
-            $both_btns
2501
-        );
2502
-    }
2503
-
2504
-
2505
-    /**
2506
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2507
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2508
-     * save, and save and close buttons to work properly, then you will want to include a
2509
-     * values for the name and id arguments.
2510
-     *
2511
-     * @param string  $name                       key used for the action ID (i.e. event_id)
2512
-     * @param int     $id                         id attached to the item published
2513
-     * @param string  $delete                     page route callback for the delete action
2514
-     * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2515
-     * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2516
-     *                                            the Save button
2517
-     * @throws EE_Error
2518
-     * @throws InvalidArgumentException
2519
-     * @throws InvalidDataTypeException
2520
-     * @throws InvalidInterfaceException
2521
-     * @todo  Add in validation for name/id arguments.
2522
-     */
2523
-    protected function _set_publish_post_box_vars(
2524
-        $name = '',
2525
-        $id = 0,
2526
-        $delete = '',
2527
-        $save_close_redirect_URL = '',
2528
-        $both_btns = true
2529
-    ) {
2530
-        // if Save & Close, use a custom redirect URL or default to the main page?
2531
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2532
-            ? $save_close_redirect_URL
2533
-            : $this->_admin_base_url;
2534
-        // create the Save & Close and Save buttons
2535
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2536
-        // if we have extra content set let's add it in if not make sure its empty
2537
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2538
-        $delete_link = '';
2539
-        if ($delete && ! empty($id)) {
2540
-            // make sure we have a default if just true is sent.
2541
-            $delete           = ! empty($delete) ? $delete : 'delete';
2542
-            $delete_link      = $this->get_action_link_or_button(
2543
-                $delete,
2544
-                $delete,
2545
-                [$name => $id],
2546
-                'submitdelete deletion button button--outline button--caution'
2547
-            );
2548
-        }
2549
-        $this->_template_args['publish_delete_link'] = $delete_link;
2550
-        if (! empty($name) && ! empty($id)) {
2551
-            $hidden_field_arr[ $name ] = [
2552
-                'type'  => 'hidden',
2553
-                'value' => $id,
2554
-            ];
2555
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2556
-        } else {
2557
-            $hf = '';
2558
-        }
2559
-        // add hidden field
2560
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2561
-            ? $hf[ $name ]['field']
2562
-            : $hf;
2563
-    }
2564
-
2565
-
2566
-    /**
2567
-     * displays an error message to ppl who have javascript disabled
2568
-     *
2569
-     * @return void
2570
-     */
2571
-    private function _display_no_javascript_warning()
2572
-    {
2573
-        ?>
2385
+	}
2386
+
2387
+
2388
+	private function _espresso_links_post_box()
2389
+	{
2390
+		// Hiding until we actually have content to put in here...
2391
+		// $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2392
+	}
2393
+
2394
+
2395
+	public function espresso_links_post_box()
2396
+	{
2397
+		// Hiding until we actually have content to put in here...
2398
+		// EEH_Template::display_template(
2399
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2400
+		// );
2401
+	}
2402
+
2403
+
2404
+	protected function _espresso_sponsors_post_box()
2405
+	{
2406
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2407
+			$this->addMetaBox(
2408
+				'espresso_sponsors_post_box',
2409
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2410
+				[$this, 'espresso_sponsors_post_box'],
2411
+				$this->_wp_page_slug,
2412
+				'side'
2413
+			);
2414
+		}
2415
+	}
2416
+
2417
+
2418
+	public function espresso_sponsors_post_box()
2419
+	{
2420
+		EEH_Template::display_template(
2421
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2422
+		);
2423
+	}
2424
+
2425
+
2426
+	private function _publish_post_box()
2427
+	{
2428
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2429
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2430
+		// then we'll use that for the metabox label.
2431
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2432
+		if (! empty($this->_labels['publishbox'])) {
2433
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2434
+				: $this->_labels['publishbox'];
2435
+		} else {
2436
+			$box_label = esc_html__('Publish', 'event_espresso');
2437
+		}
2438
+		$box_label = apply_filters(
2439
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2440
+			$box_label,
2441
+			$this->_req_action,
2442
+			$this
2443
+		);
2444
+		$this->addMetaBox(
2445
+			$meta_box_ref,
2446
+			$box_label,
2447
+			[$this, 'editor_overview'],
2448
+			$this->_current_screen->id,
2449
+			'side',
2450
+			'high'
2451
+		);
2452
+	}
2453
+
2454
+
2455
+	public function editor_overview()
2456
+	{
2457
+		// if we have extra content set let's add it in if not make sure its empty
2458
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2459
+			? $this->_template_args['publish_box_extra_content']
2460
+			: '';
2461
+		echo EEH_Template::display_template(
2462
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2463
+			$this->_template_args,
2464
+			true
2465
+		);
2466
+	}
2467
+
2468
+
2469
+	/** end of globally available metaboxes section **/
2470
+
2471
+
2472
+	/**
2473
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2474
+	 * protected method.
2475
+	 *
2476
+	 * @param string $name
2477
+	 * @param int    $id
2478
+	 * @param bool   $delete
2479
+	 * @param string $save_close_redirect_URL
2480
+	 * @param bool   $both_btns
2481
+	 * @throws EE_Error
2482
+	 * @throws InvalidArgumentException
2483
+	 * @throws InvalidDataTypeException
2484
+	 * @throws InvalidInterfaceException
2485
+	 * @see   $this->_set_publish_post_box_vars for param details
2486
+	 * @since 4.6.0
2487
+	 */
2488
+	public function set_publish_post_box_vars(
2489
+		$name = '',
2490
+		$id = 0,
2491
+		$delete = false,
2492
+		$save_close_redirect_URL = '',
2493
+		$both_btns = true
2494
+	) {
2495
+		$this->_set_publish_post_box_vars(
2496
+			$name,
2497
+			$id,
2498
+			$delete,
2499
+			$save_close_redirect_URL,
2500
+			$both_btns
2501
+		);
2502
+	}
2503
+
2504
+
2505
+	/**
2506
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2507
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2508
+	 * save, and save and close buttons to work properly, then you will want to include a
2509
+	 * values for the name and id arguments.
2510
+	 *
2511
+	 * @param string  $name                       key used for the action ID (i.e. event_id)
2512
+	 * @param int     $id                         id attached to the item published
2513
+	 * @param string  $delete                     page route callback for the delete action
2514
+	 * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2515
+	 * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2516
+	 *                                            the Save button
2517
+	 * @throws EE_Error
2518
+	 * @throws InvalidArgumentException
2519
+	 * @throws InvalidDataTypeException
2520
+	 * @throws InvalidInterfaceException
2521
+	 * @todo  Add in validation for name/id arguments.
2522
+	 */
2523
+	protected function _set_publish_post_box_vars(
2524
+		$name = '',
2525
+		$id = 0,
2526
+		$delete = '',
2527
+		$save_close_redirect_URL = '',
2528
+		$both_btns = true
2529
+	) {
2530
+		// if Save & Close, use a custom redirect URL or default to the main page?
2531
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2532
+			? $save_close_redirect_URL
2533
+			: $this->_admin_base_url;
2534
+		// create the Save & Close and Save buttons
2535
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2536
+		// if we have extra content set let's add it in if not make sure its empty
2537
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2538
+		$delete_link = '';
2539
+		if ($delete && ! empty($id)) {
2540
+			// make sure we have a default if just true is sent.
2541
+			$delete           = ! empty($delete) ? $delete : 'delete';
2542
+			$delete_link      = $this->get_action_link_or_button(
2543
+				$delete,
2544
+				$delete,
2545
+				[$name => $id],
2546
+				'submitdelete deletion button button--outline button--caution'
2547
+			);
2548
+		}
2549
+		$this->_template_args['publish_delete_link'] = $delete_link;
2550
+		if (! empty($name) && ! empty($id)) {
2551
+			$hidden_field_arr[ $name ] = [
2552
+				'type'  => 'hidden',
2553
+				'value' => $id,
2554
+			];
2555
+			$hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2556
+		} else {
2557
+			$hf = '';
2558
+		}
2559
+		// add hidden field
2560
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2561
+			? $hf[ $name ]['field']
2562
+			: $hf;
2563
+	}
2564
+
2565
+
2566
+	/**
2567
+	 * displays an error message to ppl who have javascript disabled
2568
+	 *
2569
+	 * @return void
2570
+	 */
2571
+	private function _display_no_javascript_warning()
2572
+	{
2573
+		?>
2574 2574
         <noscript>
2575 2575
             <div id="no-js-message" class="error">
2576 2576
                 <p style="font-size:1.3em;">
2577 2577
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2578 2578
                     <?php esc_html_e(
2579
-                        '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.',
2580
-                        'event_espresso'
2581
-                    ); ?>
2579
+						'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.',
2580
+						'event_espresso'
2581
+					); ?>
2582 2582
                 </p>
2583 2583
             </div>
2584 2584
         </noscript>
2585 2585
         <?php
2586
-    }
2587
-
2588
-
2589
-    /**
2590
-     * displays espresso success and/or error notices
2591
-     *
2592
-     * @return void
2593
-     */
2594
-    protected function _display_espresso_notices()
2595
-    {
2596
-        $notices = $this->_get_transient(true);
2597
-        echo stripslashes($notices);
2598
-    }
2599
-
2600
-
2601
-    /**
2602
-     * spinny things pacify the masses
2603
-     *
2604
-     * @return void
2605
-     */
2606
-    protected function _add_admin_page_ajax_loading_img()
2607
-    {
2608
-        ?>
2586
+	}
2587
+
2588
+
2589
+	/**
2590
+	 * displays espresso success and/or error notices
2591
+	 *
2592
+	 * @return void
2593
+	 */
2594
+	protected function _display_espresso_notices()
2595
+	{
2596
+		$notices = $this->_get_transient(true);
2597
+		echo stripslashes($notices);
2598
+	}
2599
+
2600
+
2601
+	/**
2602
+	 * spinny things pacify the masses
2603
+	 *
2604
+	 * @return void
2605
+	 */
2606
+	protected function _add_admin_page_ajax_loading_img()
2607
+	{
2608
+		?>
2609 2609
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2610 2610
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2611
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2611
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2612 2612
         </div>
2613 2613
         <?php
2614
-    }
2614
+	}
2615 2615
 
2616 2616
 
2617
-    /**
2618
-     * add admin page overlay for modal boxes
2619
-     *
2620
-     * @return void
2621
-     */
2622
-    protected function _add_admin_page_overlay()
2623
-    {
2624
-        ?>
2617
+	/**
2618
+	 * add admin page overlay for modal boxes
2619
+	 *
2620
+	 * @return void
2621
+	 */
2622
+	protected function _add_admin_page_overlay()
2623
+	{
2624
+		?>
2625 2625
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2626 2626
         <?php
2627
-    }
2628
-
2629
-
2630
-    /**
2631
-     * facade for $this->addMetaBox()
2632
-     *
2633
-     * @param string  $action        where the metabox gets displayed
2634
-     * @param string  $title         Title of Metabox (output in metabox header)
2635
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2636
-     *                               instead of the one created in here.
2637
-     * @param array   $callback_args an array of args supplied for the metabox
2638
-     * @param string  $column        what metabox column
2639
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2640
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2641
-     *                               created but just set our own callback for wp's add_meta_box.
2642
-     * @throws DomainException
2643
-     */
2644
-    public function _add_admin_page_meta_box(
2645
-        $action,
2646
-        $title,
2647
-        $callback,
2648
-        $callback_args,
2649
-        $column = 'normal',
2650
-        $priority = 'high',
2651
-        $create_func = true
2652
-    ) {
2653
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2654
-        // 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.
2655
-        if (empty($callback_args) && $create_func) {
2656
-            $callback_args = [
2657
-                'template_path' => $this->_template_path,
2658
-                'template_args' => $this->_template_args,
2659
-            ];
2660
-        }
2661
-        // 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)
2662
-        $call_back_func = $create_func
2663
-            ? static function ($post, $metabox) {
2664
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2665
-                echo EEH_Template::display_template(
2666
-                    $metabox['args']['template_path'],
2667
-                    $metabox['args']['template_args'],
2668
-                    true
2669
-                );
2670
-            }
2671
-            : $callback;
2672
-        $this->addMetaBox(
2673
-            str_replace('_', '-', $action) . '-mbox',
2674
-            $title,
2675
-            $call_back_func,
2676
-            $this->_wp_page_slug,
2677
-            $column,
2678
-            $priority,
2679
-            $callback_args
2680
-        );
2681
-    }
2682
-
2683
-
2684
-    /**
2685
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2686
-     *
2687
-     * @throws DomainException
2688
-     * @throws EE_Error
2689
-     * @throws InvalidArgumentException
2690
-     * @throws InvalidDataTypeException
2691
-     * @throws InvalidInterfaceException
2692
-     */
2693
-    public function display_admin_page_with_metabox_columns()
2694
-    {
2695
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2696
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2697
-            $this->_column_template_path,
2698
-            $this->_template_args,
2699
-            true
2700
-        );
2701
-        // the final wrapper
2702
-        $this->admin_page_wrapper();
2703
-    }
2704
-
2705
-
2706
-    /**
2707
-     * generates  HTML wrapper for an admin details page
2708
-     *
2709
-     * @return void
2710
-     * @throws DomainException
2711
-     * @throws EE_Error
2712
-     * @throws InvalidArgumentException
2713
-     * @throws InvalidDataTypeException
2714
-     * @throws InvalidInterfaceException
2715
-     */
2716
-    public function display_admin_page_with_sidebar()
2717
-    {
2718
-        $this->_display_admin_page(true);
2719
-    }
2720
-
2721
-
2722
-    /**
2723
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2724
-     *
2725
-     * @return void
2726
-     * @throws DomainException
2727
-     * @throws EE_Error
2728
-     * @throws InvalidArgumentException
2729
-     * @throws InvalidDataTypeException
2730
-     * @throws InvalidInterfaceException
2731
-     */
2732
-    public function display_admin_page_with_no_sidebar()
2733
-    {
2734
-        $this->_display_admin_page();
2735
-    }
2736
-
2737
-
2738
-    /**
2739
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2740
-     *
2741
-     * @return void
2742
-     * @throws DomainException
2743
-     * @throws EE_Error
2744
-     * @throws InvalidArgumentException
2745
-     * @throws InvalidDataTypeException
2746
-     * @throws InvalidInterfaceException
2747
-     */
2748
-    public function display_about_admin_page()
2749
-    {
2750
-        $this->_display_admin_page(false, true);
2751
-    }
2752
-
2753
-
2754
-    /**
2755
-     * display_admin_page
2756
-     * contains the code for actually displaying an admin page
2757
-     *
2758
-     * @param boolean $sidebar true with sidebar, false without
2759
-     * @param boolean $about   use the about admin wrapper instead of the default.
2760
-     * @return void
2761
-     * @throws DomainException
2762
-     * @throws EE_Error
2763
-     * @throws InvalidArgumentException
2764
-     * @throws InvalidDataTypeException
2765
-     * @throws InvalidInterfaceException
2766
-     */
2767
-    private function _display_admin_page($sidebar = false, $about = false)
2768
-    {
2769
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2770
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2771
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2772
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2773
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2774
-
2775
-        $post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2776
-
2777
-        $this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2778
-                                                 && $this->_req_action !== 'data_reset'
2779
-                                                 && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2780
-                                                 && strpos($post_body_content, 'wp-list-table') === false;
2781
-
2782
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2783
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2784
-            ? 'poststuff'
2785
-            : 'espresso-default-admin';
2786
-        $this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2787
-            'event-espresso_page_espresso_',
2788
-            '',
2789
-            $this->_wp_page_slug
2790
-        ) . ' ' . $this->_req_action . '-route';
2791
-
2792
-        $template_path = $sidebar
2793
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2794
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2795
-        if ($this->request->isAjax()) {
2796
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2797
-        }
2798
-        $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2799
-
2800
-        $this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2801
-        $this->_template_args['before_admin_page_content'] = $post_body_content;
2802
-        $this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2803
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2804
-            $template_path,
2805
-            $this->_template_args,
2806
-            true
2807
-        );
2808
-        // the final template wrapper
2809
-        $this->admin_page_wrapper($about);
2810
-    }
2811
-
2812
-
2813
-    /**
2814
-     * This is used to display caf preview pages.
2815
-     *
2816
-     * @param string $utm_campaign_source what is the key used for google analytics link
2817
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2818
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2819
-     * @return void
2820
-     * @throws DomainException
2821
-     * @throws EE_Error
2822
-     * @throws InvalidArgumentException
2823
-     * @throws InvalidDataTypeException
2824
-     * @throws InvalidInterfaceException
2825
-     * @since 4.3.2
2826
-     */
2827
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2828
-    {
2829
-        // let's generate a default preview action button if there isn't one already present.
2830
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2831
-            'Upgrade to Event Espresso 4 Right Now',
2832
-            'event_espresso'
2833
-        );
2834
-        $buy_now_url                                   = add_query_arg(
2835
-            [
2836
-                'ee_ver'       => 'ee4',
2837
-                'utm_source'   => 'ee4_plugin_admin',
2838
-                'utm_medium'   => 'link',
2839
-                'utm_campaign' => $utm_campaign_source,
2840
-                'utm_content'  => 'buy_now_button',
2841
-            ],
2842
-            'https://eventespresso.com/pricing/'
2843
-        );
2844
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2845
-            ? $this->get_action_link_or_button(
2846
-                '',
2847
-                'buy_now',
2848
-                [],
2849
-                'button button--primary button--big',
2850
-                esc_url_raw($buy_now_url),
2851
-                true
2852
-            )
2853
-            : $this->_template_args['preview_action_button'];
2854
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2855
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2856
-            $this->_template_args,
2857
-            true
2858
-        );
2859
-        $this->_display_admin_page($display_sidebar);
2860
-    }
2861
-
2862
-
2863
-    /**
2864
-     * display_admin_list_table_page_with_sidebar
2865
-     * generates HTML wrapper for an admin_page with list_table
2866
-     *
2867
-     * @return void
2868
-     * @throws DomainException
2869
-     * @throws EE_Error
2870
-     * @throws InvalidArgumentException
2871
-     * @throws InvalidDataTypeException
2872
-     * @throws InvalidInterfaceException
2873
-     */
2874
-    public function display_admin_list_table_page_with_sidebar()
2875
-    {
2876
-        $this->_display_admin_list_table_page(true);
2877
-    }
2878
-
2879
-
2880
-    /**
2881
-     * display_admin_list_table_page_with_no_sidebar
2882
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2883
-     *
2884
-     * @return void
2885
-     * @throws DomainException
2886
-     * @throws EE_Error
2887
-     * @throws InvalidArgumentException
2888
-     * @throws InvalidDataTypeException
2889
-     * @throws InvalidInterfaceException
2890
-     */
2891
-    public function display_admin_list_table_page_with_no_sidebar()
2892
-    {
2893
-        $this->_display_admin_list_table_page();
2894
-    }
2895
-
2896
-
2897
-    /**
2898
-     * generates html wrapper for an admin_list_table page
2899
-     *
2900
-     * @param boolean $sidebar whether to display with sidebar or not.
2901
-     * @return void
2902
-     * @throws DomainException
2903
-     * @throws EE_Error
2904
-     * @throws InvalidArgumentException
2905
-     * @throws InvalidDataTypeException
2906
-     * @throws InvalidInterfaceException
2907
-     */
2908
-    private function _display_admin_list_table_page($sidebar = false)
2909
-    {
2910
-        // setup search attributes
2911
-        $this->_set_search_attributes();
2912
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
2913
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2914
-        $this->_template_args['table_url']        = $this->request->isAjax()
2915
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2916
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2917
-        $this->_template_args['list_table']       = $this->_list_table_object;
2918
-        $this->_template_args['current_route']    = $this->_req_action;
2919
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2920
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2921
-        if (! empty($ajax_sorting_callback)) {
2922
-            $sortable_list_table_form_fields = wp_nonce_field(
2923
-                $ajax_sorting_callback . '_nonce',
2924
-                $ajax_sorting_callback . '_nonce',
2925
-                false,
2926
-                false
2927
-            );
2928
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2929
-                                                . $this->page_slug
2930
-                                                . '" />';
2931
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2932
-                                                . $ajax_sorting_callback
2933
-                                                . '" />';
2934
-        } else {
2935
-            $sortable_list_table_form_fields = '';
2936
-        }
2937
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2938
-
2939
-        $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2940
-
2941
-        $nonce_ref          = $this->_req_action . '_nonce';
2942
-        $hidden_form_fields .= '
2627
+	}
2628
+
2629
+
2630
+	/**
2631
+	 * facade for $this->addMetaBox()
2632
+	 *
2633
+	 * @param string  $action        where the metabox gets displayed
2634
+	 * @param string  $title         Title of Metabox (output in metabox header)
2635
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2636
+	 *                               instead of the one created in here.
2637
+	 * @param array   $callback_args an array of args supplied for the metabox
2638
+	 * @param string  $column        what metabox column
2639
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2640
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2641
+	 *                               created but just set our own callback for wp's add_meta_box.
2642
+	 * @throws DomainException
2643
+	 */
2644
+	public function _add_admin_page_meta_box(
2645
+		$action,
2646
+		$title,
2647
+		$callback,
2648
+		$callback_args,
2649
+		$column = 'normal',
2650
+		$priority = 'high',
2651
+		$create_func = true
2652
+	) {
2653
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2654
+		// 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.
2655
+		if (empty($callback_args) && $create_func) {
2656
+			$callback_args = [
2657
+				'template_path' => $this->_template_path,
2658
+				'template_args' => $this->_template_args,
2659
+			];
2660
+		}
2661
+		// 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)
2662
+		$call_back_func = $create_func
2663
+			? static function ($post, $metabox) {
2664
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2665
+				echo EEH_Template::display_template(
2666
+					$metabox['args']['template_path'],
2667
+					$metabox['args']['template_args'],
2668
+					true
2669
+				);
2670
+			}
2671
+			: $callback;
2672
+		$this->addMetaBox(
2673
+			str_replace('_', '-', $action) . '-mbox',
2674
+			$title,
2675
+			$call_back_func,
2676
+			$this->_wp_page_slug,
2677
+			$column,
2678
+			$priority,
2679
+			$callback_args
2680
+		);
2681
+	}
2682
+
2683
+
2684
+	/**
2685
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2686
+	 *
2687
+	 * @throws DomainException
2688
+	 * @throws EE_Error
2689
+	 * @throws InvalidArgumentException
2690
+	 * @throws InvalidDataTypeException
2691
+	 * @throws InvalidInterfaceException
2692
+	 */
2693
+	public function display_admin_page_with_metabox_columns()
2694
+	{
2695
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2696
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2697
+			$this->_column_template_path,
2698
+			$this->_template_args,
2699
+			true
2700
+		);
2701
+		// the final wrapper
2702
+		$this->admin_page_wrapper();
2703
+	}
2704
+
2705
+
2706
+	/**
2707
+	 * generates  HTML wrapper for an admin details page
2708
+	 *
2709
+	 * @return void
2710
+	 * @throws DomainException
2711
+	 * @throws EE_Error
2712
+	 * @throws InvalidArgumentException
2713
+	 * @throws InvalidDataTypeException
2714
+	 * @throws InvalidInterfaceException
2715
+	 */
2716
+	public function display_admin_page_with_sidebar()
2717
+	{
2718
+		$this->_display_admin_page(true);
2719
+	}
2720
+
2721
+
2722
+	/**
2723
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2724
+	 *
2725
+	 * @return void
2726
+	 * @throws DomainException
2727
+	 * @throws EE_Error
2728
+	 * @throws InvalidArgumentException
2729
+	 * @throws InvalidDataTypeException
2730
+	 * @throws InvalidInterfaceException
2731
+	 */
2732
+	public function display_admin_page_with_no_sidebar()
2733
+	{
2734
+		$this->_display_admin_page();
2735
+	}
2736
+
2737
+
2738
+	/**
2739
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2740
+	 *
2741
+	 * @return void
2742
+	 * @throws DomainException
2743
+	 * @throws EE_Error
2744
+	 * @throws InvalidArgumentException
2745
+	 * @throws InvalidDataTypeException
2746
+	 * @throws InvalidInterfaceException
2747
+	 */
2748
+	public function display_about_admin_page()
2749
+	{
2750
+		$this->_display_admin_page(false, true);
2751
+	}
2752
+
2753
+
2754
+	/**
2755
+	 * display_admin_page
2756
+	 * contains the code for actually displaying an admin page
2757
+	 *
2758
+	 * @param boolean $sidebar true with sidebar, false without
2759
+	 * @param boolean $about   use the about admin wrapper instead of the default.
2760
+	 * @return void
2761
+	 * @throws DomainException
2762
+	 * @throws EE_Error
2763
+	 * @throws InvalidArgumentException
2764
+	 * @throws InvalidDataTypeException
2765
+	 * @throws InvalidInterfaceException
2766
+	 */
2767
+	private function _display_admin_page($sidebar = false, $about = false)
2768
+	{
2769
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2770
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2771
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2772
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2773
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2774
+
2775
+		$post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2776
+
2777
+		$this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2778
+												 && $this->_req_action !== 'data_reset'
2779
+												 && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2780
+												 && strpos($post_body_content, 'wp-list-table') === false;
2781
+
2782
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2783
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2784
+			? 'poststuff'
2785
+			: 'espresso-default-admin';
2786
+		$this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2787
+			'event-espresso_page_espresso_',
2788
+			'',
2789
+			$this->_wp_page_slug
2790
+		) . ' ' . $this->_req_action . '-route';
2791
+
2792
+		$template_path = $sidebar
2793
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2794
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2795
+		if ($this->request->isAjax()) {
2796
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2797
+		}
2798
+		$template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2799
+
2800
+		$this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2801
+		$this->_template_args['before_admin_page_content'] = $post_body_content;
2802
+		$this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2803
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2804
+			$template_path,
2805
+			$this->_template_args,
2806
+			true
2807
+		);
2808
+		// the final template wrapper
2809
+		$this->admin_page_wrapper($about);
2810
+	}
2811
+
2812
+
2813
+	/**
2814
+	 * This is used to display caf preview pages.
2815
+	 *
2816
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2817
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2818
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2819
+	 * @return void
2820
+	 * @throws DomainException
2821
+	 * @throws EE_Error
2822
+	 * @throws InvalidArgumentException
2823
+	 * @throws InvalidDataTypeException
2824
+	 * @throws InvalidInterfaceException
2825
+	 * @since 4.3.2
2826
+	 */
2827
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2828
+	{
2829
+		// let's generate a default preview action button if there isn't one already present.
2830
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2831
+			'Upgrade to Event Espresso 4 Right Now',
2832
+			'event_espresso'
2833
+		);
2834
+		$buy_now_url                                   = add_query_arg(
2835
+			[
2836
+				'ee_ver'       => 'ee4',
2837
+				'utm_source'   => 'ee4_plugin_admin',
2838
+				'utm_medium'   => 'link',
2839
+				'utm_campaign' => $utm_campaign_source,
2840
+				'utm_content'  => 'buy_now_button',
2841
+			],
2842
+			'https://eventespresso.com/pricing/'
2843
+		);
2844
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2845
+			? $this->get_action_link_or_button(
2846
+				'',
2847
+				'buy_now',
2848
+				[],
2849
+				'button button--primary button--big',
2850
+				esc_url_raw($buy_now_url),
2851
+				true
2852
+			)
2853
+			: $this->_template_args['preview_action_button'];
2854
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2855
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2856
+			$this->_template_args,
2857
+			true
2858
+		);
2859
+		$this->_display_admin_page($display_sidebar);
2860
+	}
2861
+
2862
+
2863
+	/**
2864
+	 * display_admin_list_table_page_with_sidebar
2865
+	 * generates HTML wrapper for an admin_page with list_table
2866
+	 *
2867
+	 * @return void
2868
+	 * @throws DomainException
2869
+	 * @throws EE_Error
2870
+	 * @throws InvalidArgumentException
2871
+	 * @throws InvalidDataTypeException
2872
+	 * @throws InvalidInterfaceException
2873
+	 */
2874
+	public function display_admin_list_table_page_with_sidebar()
2875
+	{
2876
+		$this->_display_admin_list_table_page(true);
2877
+	}
2878
+
2879
+
2880
+	/**
2881
+	 * display_admin_list_table_page_with_no_sidebar
2882
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2883
+	 *
2884
+	 * @return void
2885
+	 * @throws DomainException
2886
+	 * @throws EE_Error
2887
+	 * @throws InvalidArgumentException
2888
+	 * @throws InvalidDataTypeException
2889
+	 * @throws InvalidInterfaceException
2890
+	 */
2891
+	public function display_admin_list_table_page_with_no_sidebar()
2892
+	{
2893
+		$this->_display_admin_list_table_page();
2894
+	}
2895
+
2896
+
2897
+	/**
2898
+	 * generates html wrapper for an admin_list_table page
2899
+	 *
2900
+	 * @param boolean $sidebar whether to display with sidebar or not.
2901
+	 * @return void
2902
+	 * @throws DomainException
2903
+	 * @throws EE_Error
2904
+	 * @throws InvalidArgumentException
2905
+	 * @throws InvalidDataTypeException
2906
+	 * @throws InvalidInterfaceException
2907
+	 */
2908
+	private function _display_admin_list_table_page($sidebar = false)
2909
+	{
2910
+		// setup search attributes
2911
+		$this->_set_search_attributes();
2912
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
2913
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2914
+		$this->_template_args['table_url']        = $this->request->isAjax()
2915
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2916
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2917
+		$this->_template_args['list_table']       = $this->_list_table_object;
2918
+		$this->_template_args['current_route']    = $this->_req_action;
2919
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2920
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2921
+		if (! empty($ajax_sorting_callback)) {
2922
+			$sortable_list_table_form_fields = wp_nonce_field(
2923
+				$ajax_sorting_callback . '_nonce',
2924
+				$ajax_sorting_callback . '_nonce',
2925
+				false,
2926
+				false
2927
+			);
2928
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2929
+												. $this->page_slug
2930
+												. '" />';
2931
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2932
+												. $ajax_sorting_callback
2933
+												. '" />';
2934
+		} else {
2935
+			$sortable_list_table_form_fields = '';
2936
+		}
2937
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2938
+
2939
+		$hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2940
+
2941
+		$nonce_ref          = $this->_req_action . '_nonce';
2942
+		$hidden_form_fields .= '
2943 2943
             <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2944 2944
 
2945
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2946
-        // display message about search results?
2947
-        $search = $this->request->getRequestParam('s');
2948
-        $this->_template_args['before_list_table'] .= ! empty($search)
2949
-            ? '<p class="ee-search-results">' . sprintf(
2950
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2951
-                trim($search, '%')
2952
-            ) . '</p>'
2953
-            : '';
2954
-        // filter before_list_table template arg
2955
-        $this->_template_args['before_list_table'] = apply_filters(
2956
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2957
-            $this->_template_args['before_list_table'],
2958
-            $this->page_slug,
2959
-            $this->request->requestParams(),
2960
-            $this->_req_action
2961
-        );
2962
-        // convert to array and filter again
2963
-        // arrays are easier to inject new items in a specific location,
2964
-        // but would not be backwards compatible, so we have to add a new filter
2965
-        $this->_template_args['before_list_table'] = implode(
2966
-            " \n",
2967
-            (array) apply_filters(
2968
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2969
-                (array) $this->_template_args['before_list_table'],
2970
-                $this->page_slug,
2971
-                $this->request->requestParams(),
2972
-                $this->_req_action
2973
-            )
2974
-        );
2975
-        // filter after_list_table template arg
2976
-        $this->_template_args['after_list_table'] = apply_filters(
2977
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2978
-            $this->_template_args['after_list_table'],
2979
-            $this->page_slug,
2980
-            $this->request->requestParams(),
2981
-            $this->_req_action
2982
-        );
2983
-        // convert to array and filter again
2984
-        // arrays are easier to inject new items in a specific location,
2985
-        // but would not be backwards compatible, so we have to add a new filter
2986
-        $this->_template_args['after_list_table']   = implode(
2987
-            " \n",
2988
-            (array) apply_filters(
2989
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2990
-                (array) $this->_template_args['after_list_table'],
2991
-                $this->page_slug,
2992
-                $this->request->requestParams(),
2993
-                $this->_req_action
2994
-            )
2995
-        );
2996
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2997
-            $template_path,
2998
-            $this->_template_args,
2999
-            true
3000
-        );
3001
-        // the final template wrapper
3002
-        if ($sidebar) {
3003
-            $this->display_admin_page_with_sidebar();
3004
-        } else {
3005
-            $this->display_admin_page_with_no_sidebar();
3006
-        }
3007
-    }
3008
-
3009
-
3010
-    /**
3011
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3012
-     * html string for the legend.
3013
-     * $items are expected in an array in the following format:
3014
-     * $legend_items = array(
3015
-     *        'item_id' => array(
3016
-     *            'icon' => 'http://url_to_icon_being_described.png',
3017
-     *            'desc' => esc_html__('localized description of item');
3018
-     *        )
3019
-     * );
3020
-     *
3021
-     * @param array $items see above for format of array
3022
-     * @return string html string of legend
3023
-     * @throws DomainException
3024
-     */
3025
-    protected function _display_legend($items)
3026
-    {
3027
-        $this->_template_args['items'] = apply_filters(
3028
-            'FHEE__EE_Admin_Page___display_legend__items',
3029
-            (array) $items,
3030
-            $this
3031
-        );
3032
-        /** @var StatusChangeNotice $status_change_notice */
3033
-        $status_change_notice = $this->loader->getShared(
3034
-            'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3035
-        );
3036
-        $this->_template_args['status_change_notice'] = $status_change_notice->display(
3037
-            '__admin-legend',
3038
-            $this->page_slug
3039
-        );
3040
-        return EEH_Template::display_template(
3041
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3042
-            $this->_template_args,
3043
-            true
3044
-        );
3045
-    }
3046
-
3047
-
3048
-    /**
3049
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3050
-     * The returned json object is created from an array in the following format:
3051
-     * array(
3052
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3053
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3054
-     *  'notices' => '', // - contains any EE_Error formatted notices
3055
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3056
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3057
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3058
-     *  that might be included in here)
3059
-     * )
3060
-     * The json object is populated by whatever is set in the $_template_args property.
3061
-     *
3062
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3063
-     *                                 instead of displayed.
3064
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3065
-     * @return void
3066
-     * @throws EE_Error
3067
-     * @throws InvalidArgumentException
3068
-     * @throws InvalidDataTypeException
3069
-     * @throws InvalidInterfaceException
3070
-     */
3071
-    protected function _return_json($sticky_notices = false, $notices_arguments = [])
3072
-    {
3073
-        // make sure any EE_Error notices have been handled.
3074
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3075
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3076
-        unset($this->_template_args['data']);
3077
-        $json = [
3078
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3079
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3080
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3081
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3082
-            'notices'   => EE_Error::get_notices(),
3083
-            'content'   => isset($this->_template_args['admin_page_content'])
3084
-                ? $this->_template_args['admin_page_content'] : '',
3085
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3086
-            'isEEajax'  => true
3087
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3088
-        ];
3089
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3090
-        if (null === error_get_last() || ! headers_sent()) {
3091
-            header('Content-Type: application/json; charset=UTF-8');
3092
-        }
3093
-        echo wp_json_encode($json);
3094
-        exit();
3095
-    }
3096
-
3097
-
3098
-    /**
3099
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3100
-     *
3101
-     * @return void
3102
-     * @throws EE_Error
3103
-     * @throws InvalidArgumentException
3104
-     * @throws InvalidDataTypeException
3105
-     * @throws InvalidInterfaceException
3106
-     */
3107
-    public function return_json()
3108
-    {
3109
-        if ($this->request->isAjax()) {
3110
-            $this->_return_json();
3111
-        } else {
3112
-            throw new EE_Error(
3113
-                sprintf(
3114
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3115
-                    __FUNCTION__
3116
-                )
3117
-            );
3118
-        }
3119
-    }
3120
-
3121
-
3122
-    /**
3123
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3124
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3125
-     *
3126
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3127
-     */
3128
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3129
-    {
3130
-        $this->_hook_obj = $hook_obj;
3131
-    }
3132
-
3133
-
3134
-    /**
3135
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3136
-     *
3137
-     * @param boolean $about whether to use the special about page wrapper or default.
3138
-     * @return void
3139
-     * @throws DomainException
3140
-     * @throws EE_Error
3141
-     * @throws InvalidArgumentException
3142
-     * @throws InvalidDataTypeException
3143
-     * @throws InvalidInterfaceException
3144
-     */
3145
-    public function admin_page_wrapper($about = false)
3146
-    {
3147
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3148
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3149
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3150
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3151
-
3152
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3153
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3154
-            $this->_template_args['before_admin_page_content'] ?? ''
3155
-        );
3156
-
3157
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3158
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3159
-            $this->_template_args['after_admin_page_content'] ?? ''
3160
-        );
3161
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3162
-
3163
-        if ($this->request->isAjax()) {
3164
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3165
-                // $template_path,
3166
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3167
-                $this->_template_args,
3168
-                true
3169
-            );
3170
-            $this->_return_json();
3171
-        }
3172
-        // load settings page wrapper template
3173
-        $template_path = $about
3174
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3175
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3176
-
3177
-        EEH_Template::display_template($template_path, $this->_template_args);
3178
-    }
3179
-
3180
-
3181
-    /**
3182
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3183
-     *
3184
-     * @return string html
3185
-     * @throws EE_Error
3186
-     */
3187
-    protected function _get_main_nav_tabs()
3188
-    {
3189
-        // let's generate the html using the EEH_Tabbed_Content helper.
3190
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3191
-        // (rather than setting in the page_routes array)
3192
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3193
-    }
3194
-
3195
-
3196
-    /**
3197
-     *        sort nav tabs
3198
-     *
3199
-     * @param $a
3200
-     * @param $b
3201
-     * @return int
3202
-     */
3203
-    private function _sort_nav_tabs($a, $b)
3204
-    {
3205
-        if ($a['order'] === $b['order']) {
3206
-            return 0;
3207
-        }
3208
-        return ($a['order'] < $b['order']) ? -1 : 1;
3209
-    }
3210
-
3211
-
3212
-    /**
3213
-     * generates HTML for the forms used on admin pages
3214
-     *
3215
-     * @param array  $input_vars - array of input field details
3216
-     * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3217
-     * @param bool   $id
3218
-     * @return array|string
3219
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3220
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3221
-     */
3222
-    protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3223
-    {
3224
-        return $generator === 'string'
3225
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3226
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3227
-    }
3228
-
3229
-
3230
-    /**
3231
-     * generates the "Save" and "Save & Close" buttons for edit forms
3232
-     *
3233
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3234
-     *                                   Close" button.
3235
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3236
-     *                                   'Save', [1] => 'save & close')
3237
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3238
-     *                                   via the "name" value in the button).  We can also use this to just dump
3239
-     *                                   default actions by submitting some other value.
3240
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3241
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3242
-     *                                   close (normal form handling).
3243
-     */
3244
-    protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3245
-    {
3246
-        // make sure $text and $actions are in an array
3247
-        $text          = (array) $text;
3248
-        $actions       = (array) $actions;
3249
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3250
-        $button_text   = ! empty($text)
3251
-            ? $text
3252
-            : [
3253
-                esc_html__('Save', 'event_espresso'),
3254
-                esc_html__('Save and Close', 'event_espresso'),
3255
-            ];
3256
-        $default_names = ['save', 'save_and_close'];
3257
-        $buttons = '';
3258
-        foreach ($button_text as $key => $button) {
3259
-            $ref     = $default_names[ $key ];
3260
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3261
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3262
-                        . 'value="' . $button . '" name="' . $name . '" '
3263
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3264
-            if (! $both) {
3265
-                break;
3266
-            }
3267
-        }
3268
-        // add in a hidden index for the current page (so save and close redirects properly)
3269
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3270
-                   . $referrer_url
3271
-                   . '" />';
3272
-        $this->_template_args['save_buttons'] = $buttons;
3273
-    }
3274
-
3275
-
3276
-    /**
3277
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3278
-     *
3279
-     * @param string $route
3280
-     * @param array  $additional_hidden_fields
3281
-     * @see   $this->_set_add_edit_form_tags() for details on params
3282
-     * @since 4.6.0
3283
-     */
3284
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3285
-    {
3286
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3287
-    }
3288
-
3289
-
3290
-    /**
3291
-     * set form open and close tags on add/edit pages.
3292
-     *
3293
-     * @param string $route                    the route you want the form to direct to
3294
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3295
-     * @return void
3296
-     */
3297
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3298
-    {
3299
-        if (empty($route)) {
3300
-            $user_msg = esc_html__(
3301
-                'An error occurred. No action was set for this page\'s form.',
3302
-                'event_espresso'
3303
-            );
3304
-            $dev_msg  = $user_msg . "\n"
3305
-                        . sprintf(
3306
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3307
-                            __FUNCTION__,
3308
-                            __CLASS__
3309
-                        );
3310
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3311
-        }
3312
-        // open form
3313
-        $action = $this->_admin_base_url;
3314
-        $this->_template_args['before_admin_page_content'] = "
2945
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2946
+		// display message about search results?
2947
+		$search = $this->request->getRequestParam('s');
2948
+		$this->_template_args['before_list_table'] .= ! empty($search)
2949
+			? '<p class="ee-search-results">' . sprintf(
2950
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2951
+				trim($search, '%')
2952
+			) . '</p>'
2953
+			: '';
2954
+		// filter before_list_table template arg
2955
+		$this->_template_args['before_list_table'] = apply_filters(
2956
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2957
+			$this->_template_args['before_list_table'],
2958
+			$this->page_slug,
2959
+			$this->request->requestParams(),
2960
+			$this->_req_action
2961
+		);
2962
+		// convert to array and filter again
2963
+		// arrays are easier to inject new items in a specific location,
2964
+		// but would not be backwards compatible, so we have to add a new filter
2965
+		$this->_template_args['before_list_table'] = implode(
2966
+			" \n",
2967
+			(array) apply_filters(
2968
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2969
+				(array) $this->_template_args['before_list_table'],
2970
+				$this->page_slug,
2971
+				$this->request->requestParams(),
2972
+				$this->_req_action
2973
+			)
2974
+		);
2975
+		// filter after_list_table template arg
2976
+		$this->_template_args['after_list_table'] = apply_filters(
2977
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2978
+			$this->_template_args['after_list_table'],
2979
+			$this->page_slug,
2980
+			$this->request->requestParams(),
2981
+			$this->_req_action
2982
+		);
2983
+		// convert to array and filter again
2984
+		// arrays are easier to inject new items in a specific location,
2985
+		// but would not be backwards compatible, so we have to add a new filter
2986
+		$this->_template_args['after_list_table']   = implode(
2987
+			" \n",
2988
+			(array) apply_filters(
2989
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2990
+				(array) $this->_template_args['after_list_table'],
2991
+				$this->page_slug,
2992
+				$this->request->requestParams(),
2993
+				$this->_req_action
2994
+			)
2995
+		);
2996
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2997
+			$template_path,
2998
+			$this->_template_args,
2999
+			true
3000
+		);
3001
+		// the final template wrapper
3002
+		if ($sidebar) {
3003
+			$this->display_admin_page_with_sidebar();
3004
+		} else {
3005
+			$this->display_admin_page_with_no_sidebar();
3006
+		}
3007
+	}
3008
+
3009
+
3010
+	/**
3011
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3012
+	 * html string for the legend.
3013
+	 * $items are expected in an array in the following format:
3014
+	 * $legend_items = array(
3015
+	 *        'item_id' => array(
3016
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3017
+	 *            'desc' => esc_html__('localized description of item');
3018
+	 *        )
3019
+	 * );
3020
+	 *
3021
+	 * @param array $items see above for format of array
3022
+	 * @return string html string of legend
3023
+	 * @throws DomainException
3024
+	 */
3025
+	protected function _display_legend($items)
3026
+	{
3027
+		$this->_template_args['items'] = apply_filters(
3028
+			'FHEE__EE_Admin_Page___display_legend__items',
3029
+			(array) $items,
3030
+			$this
3031
+		);
3032
+		/** @var StatusChangeNotice $status_change_notice */
3033
+		$status_change_notice = $this->loader->getShared(
3034
+			'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3035
+		);
3036
+		$this->_template_args['status_change_notice'] = $status_change_notice->display(
3037
+			'__admin-legend',
3038
+			$this->page_slug
3039
+		);
3040
+		return EEH_Template::display_template(
3041
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3042
+			$this->_template_args,
3043
+			true
3044
+		);
3045
+	}
3046
+
3047
+
3048
+	/**
3049
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3050
+	 * The returned json object is created from an array in the following format:
3051
+	 * array(
3052
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3053
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3054
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3055
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3056
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3057
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3058
+	 *  that might be included in here)
3059
+	 * )
3060
+	 * The json object is populated by whatever is set in the $_template_args property.
3061
+	 *
3062
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3063
+	 *                                 instead of displayed.
3064
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3065
+	 * @return void
3066
+	 * @throws EE_Error
3067
+	 * @throws InvalidArgumentException
3068
+	 * @throws InvalidDataTypeException
3069
+	 * @throws InvalidInterfaceException
3070
+	 */
3071
+	protected function _return_json($sticky_notices = false, $notices_arguments = [])
3072
+	{
3073
+		// make sure any EE_Error notices have been handled.
3074
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3075
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3076
+		unset($this->_template_args['data']);
3077
+		$json = [
3078
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3079
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3080
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3081
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3082
+			'notices'   => EE_Error::get_notices(),
3083
+			'content'   => isset($this->_template_args['admin_page_content'])
3084
+				? $this->_template_args['admin_page_content'] : '',
3085
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3086
+			'isEEajax'  => true
3087
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3088
+		];
3089
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3090
+		if (null === error_get_last() || ! headers_sent()) {
3091
+			header('Content-Type: application/json; charset=UTF-8');
3092
+		}
3093
+		echo wp_json_encode($json);
3094
+		exit();
3095
+	}
3096
+
3097
+
3098
+	/**
3099
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3100
+	 *
3101
+	 * @return void
3102
+	 * @throws EE_Error
3103
+	 * @throws InvalidArgumentException
3104
+	 * @throws InvalidDataTypeException
3105
+	 * @throws InvalidInterfaceException
3106
+	 */
3107
+	public function return_json()
3108
+	{
3109
+		if ($this->request->isAjax()) {
3110
+			$this->_return_json();
3111
+		} else {
3112
+			throw new EE_Error(
3113
+				sprintf(
3114
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3115
+					__FUNCTION__
3116
+				)
3117
+			);
3118
+		}
3119
+	}
3120
+
3121
+
3122
+	/**
3123
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3124
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3125
+	 *
3126
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3127
+	 */
3128
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3129
+	{
3130
+		$this->_hook_obj = $hook_obj;
3131
+	}
3132
+
3133
+
3134
+	/**
3135
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3136
+	 *
3137
+	 * @param boolean $about whether to use the special about page wrapper or default.
3138
+	 * @return void
3139
+	 * @throws DomainException
3140
+	 * @throws EE_Error
3141
+	 * @throws InvalidArgumentException
3142
+	 * @throws InvalidDataTypeException
3143
+	 * @throws InvalidInterfaceException
3144
+	 */
3145
+	public function admin_page_wrapper($about = false)
3146
+	{
3147
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3148
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3149
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3150
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3151
+
3152
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3153
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3154
+			$this->_template_args['before_admin_page_content'] ?? ''
3155
+		);
3156
+
3157
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3158
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3159
+			$this->_template_args['after_admin_page_content'] ?? ''
3160
+		);
3161
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3162
+
3163
+		if ($this->request->isAjax()) {
3164
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3165
+				// $template_path,
3166
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3167
+				$this->_template_args,
3168
+				true
3169
+			);
3170
+			$this->_return_json();
3171
+		}
3172
+		// load settings page wrapper template
3173
+		$template_path = $about
3174
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3175
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3176
+
3177
+		EEH_Template::display_template($template_path, $this->_template_args);
3178
+	}
3179
+
3180
+
3181
+	/**
3182
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3183
+	 *
3184
+	 * @return string html
3185
+	 * @throws EE_Error
3186
+	 */
3187
+	protected function _get_main_nav_tabs()
3188
+	{
3189
+		// let's generate the html using the EEH_Tabbed_Content helper.
3190
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3191
+		// (rather than setting in the page_routes array)
3192
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3193
+	}
3194
+
3195
+
3196
+	/**
3197
+	 *        sort nav tabs
3198
+	 *
3199
+	 * @param $a
3200
+	 * @param $b
3201
+	 * @return int
3202
+	 */
3203
+	private function _sort_nav_tabs($a, $b)
3204
+	{
3205
+		if ($a['order'] === $b['order']) {
3206
+			return 0;
3207
+		}
3208
+		return ($a['order'] < $b['order']) ? -1 : 1;
3209
+	}
3210
+
3211
+
3212
+	/**
3213
+	 * generates HTML for the forms used on admin pages
3214
+	 *
3215
+	 * @param array  $input_vars - array of input field details
3216
+	 * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3217
+	 * @param bool   $id
3218
+	 * @return array|string
3219
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3220
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3221
+	 */
3222
+	protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3223
+	{
3224
+		return $generator === 'string'
3225
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3226
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3227
+	}
3228
+
3229
+
3230
+	/**
3231
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3232
+	 *
3233
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3234
+	 *                                   Close" button.
3235
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3236
+	 *                                   'Save', [1] => 'save & close')
3237
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3238
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3239
+	 *                                   default actions by submitting some other value.
3240
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3241
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3242
+	 *                                   close (normal form handling).
3243
+	 */
3244
+	protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3245
+	{
3246
+		// make sure $text and $actions are in an array
3247
+		$text          = (array) $text;
3248
+		$actions       = (array) $actions;
3249
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3250
+		$button_text   = ! empty($text)
3251
+			? $text
3252
+			: [
3253
+				esc_html__('Save', 'event_espresso'),
3254
+				esc_html__('Save and Close', 'event_espresso'),
3255
+			];
3256
+		$default_names = ['save', 'save_and_close'];
3257
+		$buttons = '';
3258
+		foreach ($button_text as $key => $button) {
3259
+			$ref     = $default_names[ $key ];
3260
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3261
+			$buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3262
+						. 'value="' . $button . '" name="' . $name . '" '
3263
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3264
+			if (! $both) {
3265
+				break;
3266
+			}
3267
+		}
3268
+		// add in a hidden index for the current page (so save and close redirects properly)
3269
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3270
+				   . $referrer_url
3271
+				   . '" />';
3272
+		$this->_template_args['save_buttons'] = $buttons;
3273
+	}
3274
+
3275
+
3276
+	/**
3277
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3278
+	 *
3279
+	 * @param string $route
3280
+	 * @param array  $additional_hidden_fields
3281
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3282
+	 * @since 4.6.0
3283
+	 */
3284
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3285
+	{
3286
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3287
+	}
3288
+
3289
+
3290
+	/**
3291
+	 * set form open and close tags on add/edit pages.
3292
+	 *
3293
+	 * @param string $route                    the route you want the form to direct to
3294
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3295
+	 * @return void
3296
+	 */
3297
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3298
+	{
3299
+		if (empty($route)) {
3300
+			$user_msg = esc_html__(
3301
+				'An error occurred. No action was set for this page\'s form.',
3302
+				'event_espresso'
3303
+			);
3304
+			$dev_msg  = $user_msg . "\n"
3305
+						. sprintf(
3306
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3307
+							__FUNCTION__,
3308
+							__CLASS__
3309
+						);
3310
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3311
+		}
3312
+		// open form
3313
+		$action = $this->_admin_base_url;
3314
+		$this->_template_args['before_admin_page_content'] = "
3315 3315
             <form name='form' method='post' action='{$action}' id='{$route}_event_form' class='ee-admin-page-form' >
3316 3316
             ";
3317
-        // add nonce
3318
-        $nonce                                             =
3319
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3320
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3321
-        // add REQUIRED form action
3322
-        $hidden_fields = [
3323
-            'action' => ['type' => 'hidden', 'value' => $route],
3324
-        ];
3325
-        // merge arrays
3326
-        $hidden_fields = is_array($additional_hidden_fields)
3327
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3328
-            : $hidden_fields;
3329
-        // generate form fields
3330
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3331
-        // add fields to form
3332
-        foreach ((array) $form_fields as $form_field) {
3333
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3334
-        }
3335
-        // close form
3336
-        $this->_template_args['after_admin_page_content'] = '</form>';
3337
-    }
3338
-
3339
-
3340
-    /**
3341
-     * Public Wrapper for _redirect_after_action() method since its
3342
-     * discovered it would be useful for external code to have access.
3343
-     *
3344
-     * @param bool   $success
3345
-     * @param string $what
3346
-     * @param string $action_desc
3347
-     * @param array  $query_args
3348
-     * @param bool   $override_overwrite
3349
-     * @throws EE_Error
3350
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3351
-     * @since 4.5.0
3352
-     */
3353
-    public function redirect_after_action(
3354
-        $success = false,
3355
-        $what = 'item',
3356
-        $action_desc = 'processed',
3357
-        $query_args = [],
3358
-        $override_overwrite = false
3359
-    ) {
3360
-        $this->_redirect_after_action(
3361
-            $success,
3362
-            $what,
3363
-            $action_desc,
3364
-            $query_args,
3365
-            $override_overwrite
3366
-        );
3367
-    }
3368
-
3369
-
3370
-    /**
3371
-     * Helper method for merging existing request data with the returned redirect url.
3372
-     *
3373
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3374
-     * filters are still applied.
3375
-     *
3376
-     * @param array $new_route_data
3377
-     * @return array
3378
-     */
3379
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3380
-    {
3381
-        foreach ($this->request->requestParams() as $ref => $value) {
3382
-            // unset nonces
3383
-            if (strpos($ref, 'nonce') !== false) {
3384
-                $this->request->unSetRequestParam($ref);
3385
-                continue;
3386
-            }
3387
-            // urlencode values.
3388
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3389
-            $this->request->setRequestParam($ref, $value);
3390
-        }
3391
-        return array_merge($this->request->requestParams(), $new_route_data);
3392
-    }
3393
-
3394
-
3395
-    /**
3396
-     * @param int|float|string $success      - whether success was for two or more records, or just one, or none
3397
-     * @param string           $what         - what the action was performed on
3398
-     * @param string           $action_desc  - what was done ie: updated, deleted, etc
3399
-     * @param array $query_args              - an array of query_args to be added to the URL to redirect to
3400
-     * @param BOOL $override_overwrite       - by default all EE_Error::success messages are overwritten,
3401
-     *                                         this allows you to override this so that they show.
3402
-     * @return void
3403
-     * @throws EE_Error
3404
-     * @throws InvalidArgumentException
3405
-     * @throws InvalidDataTypeException
3406
-     * @throws InvalidInterfaceException
3407
-     */
3408
-    protected function _redirect_after_action(
3409
-        $success = 0,
3410
-        string $what = 'item',
3411
-        string $action_desc = 'processed',
3412
-        array $query_args = [],
3413
-        bool $override_overwrite = false
3414
-    ) {
3415
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3416
-        $notices      = EE_Error::get_notices(false);
3417
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3418
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3419
-            EE_Error::overwrite_success();
3420
-        }
3421
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3422
-            // how many records affected ? more than one record ? or just one ?
3423
-            EE_Error::add_success(
3424
-                sprintf(
3425
-                    esc_html(
3426
-                        _n(
3427
-                            'The "%1$s" has been successfully %2$s.',
3428
-                            'The "%1$s" have been successfully %2$s.',
3429
-                            $success,
3430
-                            'event_espresso'
3431
-                        )
3432
-                    ),
3433
-                    $what,
3434
-                    $action_desc
3435
-                ),
3436
-                __FILE__,
3437
-                __FUNCTION__,
3438
-                __LINE__
3439
-            );
3440
-        }
3441
-        // check that $query_args isn't something crazy
3442
-        if (! is_array($query_args)) {
3443
-            $query_args = [];
3444
-        }
3445
-        /**
3446
-         * Allow injecting actions before the query_args are modified for possible different
3447
-         * redirections on save and close actions
3448
-         *
3449
-         * @param array $query_args       The original query_args array coming into the
3450
-         *                                method.
3451
-         * @since 4.2.0
3452
-         */
3453
-        do_action(
3454
-            "AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3455
-            $query_args
3456
-        );
3457
-        // set redirect url.
3458
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3459
-        // otherwise we go with whatever is set as the _admin_base_url
3460
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3461
-        // calculate where we're going (if we have a "save and close" button pushed)
3462
-        if (
3463
-            $this->request->requestParamIsSet('save_and_close')
3464
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3465
-        ) {
3466
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3467
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3468
-            // regenerate query args array from referrer URL
3469
-            parse_str($parsed_url['query'], $query_args);
3470
-            // correct page and action will be in the query args now
3471
-            $redirect_url = admin_url('admin.php');
3472
-        }
3473
-        // merge any default query_args set in _default_route_query_args property
3474
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3475
-            $args_to_merge = [];
3476
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3477
-                // is there a wp_referer array in our _default_route_query_args property?
3478
-                if ($query_param === 'wp_referer') {
3479
-                    $query_value = (array) $query_value;
3480
-                    foreach ($query_value as $reference => $value) {
3481
-                        if (strpos($reference, 'nonce') !== false) {
3482
-                            continue;
3483
-                        }
3484
-                        // finally we will override any arguments in the referer with
3485
-                        // what might be set on the _default_route_query_args array.
3486
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3487
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3488
-                        } else {
3489
-                            $args_to_merge[ $reference ] = urlencode($value);
3490
-                        }
3491
-                    }
3492
-                    continue;
3493
-                }
3494
-                $args_to_merge[ $query_param ] = $query_value;
3495
-            }
3496
-            // now let's merge these arguments but override with what was specifically sent in to the
3497
-            // redirect.
3498
-            $query_args = array_merge($args_to_merge, $query_args);
3499
-        }
3500
-        $this->_process_notices($query_args);
3501
-        // generate redirect url
3502
-        // if redirecting to anything other than the main page, add a nonce
3503
-        if (isset($query_args['action'])) {
3504
-            // manually generate wp_nonce and merge that with the query vars
3505
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3506
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3507
-        }
3508
-        // we're adding some hooks and filters in here for processing any things just before redirects
3509
-        // (example: an admin page has done an insert or update and we want to run something after that).
3510
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3511
-        $redirect_url = apply_filters(
3512
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3513
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3514
-            $query_args
3515
-        );
3516
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3517
-        if ($this->request->isAjax()) {
3518
-            $default_data                    = [
3519
-                'close'        => true,
3520
-                'redirect_url' => $redirect_url,
3521
-                'where'        => 'main',
3522
-                'what'         => 'append',
3523
-            ];
3524
-            $this->_template_args['success'] = $success;
3525
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3526
-                $default_data,
3527
-                $this->_template_args['data']
3528
-            ) : $default_data;
3529
-            $this->_return_json();
3530
-        }
3531
-        wp_safe_redirect($redirect_url);
3532
-        exit();
3533
-    }
3534
-
3535
-
3536
-    /**
3537
-     * process any notices before redirecting (or returning ajax request)
3538
-     * This method sets the $this->_template_args['notices'] attribute;
3539
-     *
3540
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3541
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3542
-     *                                  page_routes haven't been defined yet.
3543
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3544
-     *                                  still save a transient for the notice.
3545
-     * @return void
3546
-     * @throws EE_Error
3547
-     * @throws InvalidArgumentException
3548
-     * @throws InvalidDataTypeException
3549
-     * @throws InvalidInterfaceException
3550
-     */
3551
-    protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3552
-    {
3553
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3554
-        if ($this->request->isAjax()) {
3555
-            $notices = EE_Error::get_notices(false);
3556
-            if (empty($this->_template_args['success'])) {
3557
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3558
-            }
3559
-            if (empty($this->_template_args['errors'])) {
3560
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3561
-            }
3562
-            if (empty($this->_template_args['attention'])) {
3563
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3564
-            }
3565
-        }
3566
-        $this->_template_args['notices'] = EE_Error::get_notices();
3567
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3568
-        if (! $this->request->isAjax() || $sticky_notices) {
3569
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3570
-            $this->_add_transient(
3571
-                $route,
3572
-                $this->_template_args['notices'],
3573
-                true,
3574
-                $skip_route_verify
3575
-            );
3576
-        }
3577
-    }
3578
-
3579
-
3580
-    /**
3581
-     * get_action_link_or_button
3582
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3583
-     *
3584
-     * @param string $action        use this to indicate which action the url is generated with.
3585
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3586
-     *                              property.
3587
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3588
-     * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3589
-     * @param string $base_url      If this is not provided
3590
-     *                              the _admin_base_url will be used as the default for the button base_url.
3591
-     *                              Otherwise this value will be used.
3592
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3593
-     * @return string
3594
-     * @throws InvalidArgumentException
3595
-     * @throws InvalidInterfaceException
3596
-     * @throws InvalidDataTypeException
3597
-     * @throws EE_Error
3598
-     */
3599
-    public function get_action_link_or_button(
3600
-        $action,
3601
-        $type = 'add',
3602
-        $extra_request = [],
3603
-        $class = 'button--primary',
3604
-        $base_url = '',
3605
-        $exclude_nonce = false
3606
-    ) {
3607
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3608
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3609
-            throw new EE_Error(
3610
-                sprintf(
3611
-                    esc_html__(
3612
-                        'There is no page route for given action for the button.  This action was given: %s',
3613
-                        'event_espresso'
3614
-                    ),
3615
-                    $action
3616
-                )
3617
-            );
3618
-        }
3619
-        if (! isset($this->_labels['buttons'][ $type ])) {
3620
-            throw new EE_Error(
3621
-                sprintf(
3622
-                    esc_html__(
3623
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3624
-                        'event_espresso'
3625
-                    ),
3626
-                    $type
3627
-                )
3628
-            );
3629
-        }
3630
-        // finally check user access for this button.
3631
-        $has_access = $this->check_user_access($action, true);
3632
-        if (! $has_access) {
3633
-            return '';
3634
-        }
3635
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3636
-        $query_args = [
3637
-            'action' => $action,
3638
-        ];
3639
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3640
-        if (! empty($extra_request)) {
3641
-            $query_args = array_merge($extra_request, $query_args);
3642
-        }
3643
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3644
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3645
-    }
3646
-
3647
-
3648
-    /**
3649
-     * _per_page_screen_option
3650
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3651
-     *
3652
-     * @return void
3653
-     * @throws InvalidArgumentException
3654
-     * @throws InvalidInterfaceException
3655
-     * @throws InvalidDataTypeException
3656
-     */
3657
-    protected function _per_page_screen_option()
3658
-    {
3659
-        $option = 'per_page';
3660
-        $args   = [
3661
-            'label'   => apply_filters(
3662
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3663
-                $this->_admin_page_title,
3664
-                $this
3665
-            ),
3666
-            'default' => (int) apply_filters(
3667
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3668
-                20
3669
-            ),
3670
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3671
-        ];
3672
-        // ONLY add the screen option if the user has access to it.
3673
-        if ($this->check_user_access($this->_current_view, true)) {
3674
-            add_screen_option($option, $args);
3675
-        }
3676
-    }
3677
-
3678
-
3679
-    /**
3680
-     * set_per_page_screen_option
3681
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3682
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3683
-     * admin_menu.
3684
-     *
3685
-     * @return void
3686
-     */
3687
-    private function _set_per_page_screen_options()
3688
-    {
3689
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3690
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3691
-            if (! $user = wp_get_current_user()) {
3692
-                return;
3693
-            }
3694
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3695
-            if (! $option) {
3696
-                return;
3697
-            }
3698
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3699
-            $map_option = $option;
3700
-            $option     = str_replace('-', '_', $option);
3701
-            switch ($map_option) {
3702
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3703
-                    $max_value = apply_filters(
3704
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3705
-                        999,
3706
-                        $this->_current_page,
3707
-                        $this->_current_view
3708
-                    );
3709
-                    if ($value < 1) {
3710
-                        return;
3711
-                    }
3712
-                    $value = min($value, $max_value);
3713
-                    break;
3714
-                default:
3715
-                    $value = apply_filters(
3716
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3717
-                        false,
3718
-                        $option,
3719
-                        $value
3720
-                    );
3721
-                    if (false === $value) {
3722
-                        return;
3723
-                    }
3724
-                    break;
3725
-            }
3726
-            update_user_meta($user->ID, $option, $value);
3727
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3728
-            exit;
3729
-        }
3730
-    }
3731
-
3732
-
3733
-    /**
3734
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3735
-     *
3736
-     * @param array $data array that will be assigned to template args.
3737
-     */
3738
-    public function set_template_args($data)
3739
-    {
3740
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3741
-    }
3742
-
3743
-
3744
-    /**
3745
-     * This makes available the WP transient system for temporarily moving data between routes
3746
-     *
3747
-     * @param string $route             the route that should receive the transient
3748
-     * @param array  $data              the data that gets sent
3749
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3750
-     *                                  normal route transient.
3751
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3752
-     *                                  when we are adding a transient before page_routes have been defined.
3753
-     * @return void
3754
-     * @throws EE_Error
3755
-     */
3756
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3757
-    {
3758
-        $user_id = get_current_user_id();
3759
-        if (! $skip_route_verify) {
3760
-            $this->_verify_route($route);
3761
-        }
3762
-        // now let's set the string for what kind of transient we're setting
3763
-        $transient = $notices
3764
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3765
-            : 'rte_tx_' . $route . '_' . $user_id;
3766
-        $data      = $notices ? ['notices' => $data] : $data;
3767
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3768
-        $existing = is_multisite() && is_network_admin()
3769
-            ? get_site_transient($transient)
3770
-            : get_transient($transient);
3771
-        if ($existing) {
3772
-            $data = array_merge((array) $data, (array) $existing);
3773
-        }
3774
-        if (is_multisite() && is_network_admin()) {
3775
-            set_site_transient($transient, $data, 8);
3776
-        } else {
3777
-            set_transient($transient, $data, 8);
3778
-        }
3779
-    }
3780
-
3781
-
3782
-    /**
3783
-     * this retrieves the temporary transient that has been set for moving data between routes.
3784
-     *
3785
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3786
-     * @param string $route
3787
-     * @return mixed data
3788
-     */
3789
-    protected function _get_transient($notices = false, $route = '')
3790
-    {
3791
-        $user_id   = get_current_user_id();
3792
-        $route     = ! $route ? $this->_req_action : $route;
3793
-        $transient = $notices
3794
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3795
-            : 'rte_tx_' . $route . '_' . $user_id;
3796
-        $data      = is_multisite() && is_network_admin()
3797
-            ? get_site_transient($transient)
3798
-            : get_transient($transient);
3799
-        // delete transient after retrieval (just in case it hasn't expired);
3800
-        if (is_multisite() && is_network_admin()) {
3801
-            delete_site_transient($transient);
3802
-        } else {
3803
-            delete_transient($transient);
3804
-        }
3805
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3806
-    }
3807
-
3808
-
3809
-    /**
3810
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3811
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3812
-     * default route callback on the EE_Admin page you want it run.)
3813
-     *
3814
-     * @return void
3815
-     */
3816
-    protected function _transient_garbage_collection()
3817
-    {
3818
-        global $wpdb;
3819
-        // retrieve all existing transients
3820
-        $query =
3821
-            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3822
-        if ($results = $wpdb->get_results($query)) {
3823
-            foreach ($results as $result) {
3824
-                $transient = str_replace('_transient_', '', $result->option_name);
3825
-                get_transient($transient);
3826
-                if (is_multisite() && is_network_admin()) {
3827
-                    get_site_transient($transient);
3828
-                }
3829
-            }
3830
-        }
3831
-    }
3832
-
3833
-
3834
-    /**
3835
-     * get_view
3836
-     *
3837
-     * @return string content of _view property
3838
-     */
3839
-    public function get_view()
3840
-    {
3841
-        return $this->_view;
3842
-    }
3843
-
3844
-
3845
-    /**
3846
-     * getter for the protected $_views property
3847
-     *
3848
-     * @return array
3849
-     */
3850
-    public function get_views()
3851
-    {
3852
-        return $this->_views;
3853
-    }
3854
-
3855
-
3856
-    /**
3857
-     * get_current_page
3858
-     *
3859
-     * @return string _current_page property value
3860
-     */
3861
-    public function get_current_page()
3862
-    {
3863
-        return $this->_current_page;
3864
-    }
3865
-
3866
-
3867
-    /**
3868
-     * get_current_view
3869
-     *
3870
-     * @return string _current_view property value
3871
-     */
3872
-    public function get_current_view()
3873
-    {
3874
-        return $this->_current_view;
3875
-    }
3876
-
3877
-
3878
-    /**
3879
-     * get_current_screen
3880
-     *
3881
-     * @return object The current WP_Screen object
3882
-     */
3883
-    public function get_current_screen()
3884
-    {
3885
-        return $this->_current_screen;
3886
-    }
3887
-
3888
-
3889
-    /**
3890
-     * get_current_page_view_url
3891
-     *
3892
-     * @return string This returns the url for the current_page_view.
3893
-     */
3894
-    public function get_current_page_view_url()
3895
-    {
3896
-        return $this->_current_page_view_url;
3897
-    }
3898
-
3899
-
3900
-    /**
3901
-     * just returns the Request
3902
-     *
3903
-     * @return RequestInterface
3904
-     */
3905
-    public function get_request()
3906
-    {
3907
-        return $this->request;
3908
-    }
3909
-
3910
-
3911
-    /**
3912
-     * just returns the _req_data property
3913
-     *
3914
-     * @return array
3915
-     */
3916
-    public function get_request_data()
3917
-    {
3918
-        return $this->request->requestParams();
3919
-    }
3920
-
3921
-
3922
-    /**
3923
-     * returns the _req_data protected property
3924
-     *
3925
-     * @return string
3926
-     */
3927
-    public function get_req_action()
3928
-    {
3929
-        return $this->_req_action;
3930
-    }
3931
-
3932
-
3933
-    /**
3934
-     * @return bool  value of $_is_caf property
3935
-     */
3936
-    public function is_caf()
3937
-    {
3938
-        return $this->_is_caf;
3939
-    }
3940
-
3941
-
3942
-    /**
3943
-     * @return mixed
3944
-     */
3945
-    public function default_espresso_metaboxes()
3946
-    {
3947
-        return $this->_default_espresso_metaboxes;
3948
-    }
3949
-
3950
-
3951
-    /**
3952
-     * @return mixed
3953
-     */
3954
-    public function admin_base_url()
3955
-    {
3956
-        return $this->_admin_base_url;
3957
-    }
3958
-
3959
-
3960
-    /**
3961
-     * @return mixed
3962
-     */
3963
-    public function wp_page_slug()
3964
-    {
3965
-        return $this->_wp_page_slug;
3966
-    }
3967
-
3968
-
3969
-    /**
3970
-     * updates  espresso configuration settings
3971
-     *
3972
-     * @param string                   $tab
3973
-     * @param EE_Config_Base|EE_Config $config
3974
-     * @param string                   $file file where error occurred
3975
-     * @param string                   $func function  where error occurred
3976
-     * @param string                   $line line no where error occurred
3977
-     * @return boolean
3978
-     */
3979
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3980
-    {
3981
-        // remove any options that are NOT going to be saved with the config settings.
3982
-        if (isset($config->core->ee_ueip_optin)) {
3983
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
3984
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3985
-            update_option('ee_ueip_has_notified', true);
3986
-        }
3987
-        // and save it (note we're also doing the network save here)
3988
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3989
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
3990
-        if ($config_saved && $net_saved) {
3991
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3992
-            return true;
3993
-        }
3994
-        EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3995
-        return false;
3996
-    }
3997
-
3998
-
3999
-    /**
4000
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4001
-     *
4002
-     * @return array
4003
-     */
4004
-    public function get_yes_no_values()
4005
-    {
4006
-        return $this->_yes_no_values;
4007
-    }
4008
-
4009
-
4010
-    /**
4011
-     * @return string
4012
-     * @throws ReflectionException
4013
-     * @since $VID:$
4014
-     */
4015
-    protected function _get_dir()
4016
-    {
4017
-        $reflector = new ReflectionClass($this->class_name);
4018
-        return dirname($reflector->getFileName());
4019
-    }
4020
-
4021
-
4022
-    /**
4023
-     * A helper for getting a "next link".
4024
-     *
4025
-     * @param string $url   The url to link to
4026
-     * @param string $class The class to use.
4027
-     * @return string
4028
-     */
4029
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4030
-    {
4031
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4032
-    }
4033
-
4034
-
4035
-    /**
4036
-     * A helper for getting a "previous link".
4037
-     *
4038
-     * @param string $url   The url to link to
4039
-     * @param string $class The class to use.
4040
-     * @return string
4041
-     */
4042
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4043
-    {
4044
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4045
-    }
4046
-
4047
-
4048
-
4049
-
4050
-
4051
-
4052
-
4053
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4054
-
4055
-
4056
-    /**
4057
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4058
-     * 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
4059
-     * _req_data array.
4060
-     *
4061
-     * @return bool success/fail
4062
-     * @throws EE_Error
4063
-     * @throws InvalidArgumentException
4064
-     * @throws ReflectionException
4065
-     * @throws InvalidDataTypeException
4066
-     * @throws InvalidInterfaceException
4067
-     */
4068
-    protected function _process_resend_registration()
4069
-    {
4070
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4071
-        do_action(
4072
-            'AHEE__EE_Admin_Page___process_resend_registration',
4073
-            $this->_template_args['success'],
4074
-            $this->request->requestParams()
4075
-        );
4076
-        return $this->_template_args['success'];
4077
-    }
4078
-
4079
-
4080
-    /**
4081
-     * This automatically processes any payment message notifications when manual payment has been applied.
4082
-     *
4083
-     * @param EE_Payment $payment
4084
-     * @return bool success/fail
4085
-     */
4086
-    protected function _process_payment_notification(EE_Payment $payment)
4087
-    {
4088
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4089
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4090
-        $this->_template_args['success'] = apply_filters(
4091
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4092
-            false,
4093
-            $payment
4094
-        );
4095
-        return $this->_template_args['success'];
4096
-    }
4097
-
4098
-
4099
-    /**
4100
-     * @param EEM_Base      $entity_model
4101
-     * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4102
-     * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4103
-     * @param string        $delete_column  name of the field that denotes whether entity is trashed
4104
-     * @param callable|null $callback       called after entity is trashed, restored, or deleted
4105
-     * @return int|float
4106
-     * @throws EE_Error
4107
-     */
4108
-    protected function trashRestoreDeleteEntities(
4109
-        EEM_Base $entity_model,
4110
-        string $entity_PK_name,
4111
-        string $action = EE_Admin_List_Table::ACTION_DELETE,
4112
-        string $delete_column = '',
4113
-        callable $callback = null
4114
-    ) {
4115
-        $entity_PK      = $entity_model->get_primary_key_field();
4116
-        $entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4117
-        $entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4118
-        // grab ID if deleting a single entity
4119
-        if ($this->request->requestParamIsSet($entity_PK_name)) {
4120
-            $ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4121
-            return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4122
-        }
4123
-        // or grab checkbox array if bulk deleting
4124
-        $checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4125
-        if (empty($checkboxes)) {
4126
-            return 0;
4127
-        }
4128
-        $success = 0;
4129
-        $IDs     = array_keys($checkboxes);
4130
-        // cycle thru bulk action checkboxes
4131
-        foreach ($IDs as $ID) {
4132
-            // increment $success
4133
-            if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4134
-                $success++;
4135
-            }
4136
-        }
4137
-        $count = (int) count($checkboxes);
4138
-        // if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4139
-        // otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4140
-        return $success === $count ? $count : $success / $count;
4141
-    }
4142
-
4143
-
4144
-    /**
4145
-     * @param EE_Primary_Key_Field_Base $entity_PK
4146
-     * @return string
4147
-     * @throws EE_Error
4148
-     * @since   4.10.30.p
4149
-     */
4150
-    private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4151
-    {
4152
-        $entity_PK_type = $entity_PK->getSchemaType();
4153
-        switch ($entity_PK_type) {
4154
-            case 'boolean':
4155
-                return 'bool';
4156
-            case 'integer':
4157
-                return 'int';
4158
-            case 'number':
4159
-                return 'float';
4160
-            case 'string':
4161
-                return 'string';
4162
-        }
4163
-        throw new RuntimeException(
4164
-            sprintf(
4165
-                esc_html__(
4166
-                    '"%1$s" is an invalid schema type for the %2$s primary key.',
4167
-                    'event_espresso'
4168
-                ),
4169
-                $entity_PK_type,
4170
-                $entity_PK->get_name()
4171
-            )
4172
-        );
4173
-    }
4174
-
4175
-
4176
-    /**
4177
-     * @param EEM_Base      $entity_model
4178
-     * @param int|string    $entity_ID
4179
-     * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4180
-     * @param string        $delete_column name of the field that denotes whether entity is trashed
4181
-     * @param callable|null $callback      called after entity is trashed, restored, or deleted
4182
-     * @return bool
4183
-     */
4184
-    protected function trashRestoreDeleteEntity(
4185
-        EEM_Base $entity_model,
4186
-        $entity_ID,
4187
-        string $action,
4188
-        string $delete_column,
4189
-        ?callable $callback = null
4190
-    ): bool {
4191
-        $entity_ID = absint($entity_ID);
4192
-        if (! $entity_ID) {
4193
-            $this->trashRestoreDeleteError($action, $entity_model);
4194
-        }
4195
-        $result = 0;
4196
-        try {
4197
-            switch ($action) {
4198
-                case EE_Admin_List_Table::ACTION_DELETE:
4199
-                    $result = (bool) $entity_model->delete_permanently_by_ID($entity_ID);
4200
-                    break;
4201
-                case EE_Admin_List_Table::ACTION_RESTORE:
4202
-                    $this->validateDeleteColumn($entity_model, $delete_column);
4203
-                    $result = $entity_model->update_by_ID([$delete_column => 0], $entity_ID);
4204
-                    break;
4205
-                case EE_Admin_List_Table::ACTION_TRASH:
4206
-                    $this->validateDeleteColumn($entity_model, $delete_column);
4207
-                    $result = $entity_model->update_by_ID([$delete_column => 1], $entity_ID);
4208
-                    break;
4209
-            }
4210
-        } catch (Exception $exception) {
4211
-            $this->trashRestoreDeleteError($action, $entity_model, $exception);
4212
-        }
4213
-        if (is_callable($callback)) {
4214
-            call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4215
-        }
4216
-        return $result;
4217
-    }
4218
-
4219
-
4220
-    /**
4221
-     * @param EEM_Base $entity_model
4222
-     * @param string   $delete_column
4223
-     * @since 4.10.30.p
4224
-     */
4225
-    private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4226
-    {
4227
-        if (empty($delete_column)) {
4228
-            throw new DomainException(
4229
-                sprintf(
4230
-                    esc_html__(
4231
-                        'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4232
-                        'event_espresso'
4233
-                    ),
4234
-                    $entity_model->get_this_model_name()
4235
-                )
4236
-            );
4237
-        }
4238
-        if (! $entity_model->has_field($delete_column)) {
4239
-            throw new DomainException(
4240
-                sprintf(
4241
-                    esc_html__(
4242
-                        'The %1$s field does not exist on the %2$s model.',
4243
-                        'event_espresso'
4244
-                    ),
4245
-                    $delete_column,
4246
-                    $entity_model->get_this_model_name()
4247
-                )
4248
-            );
4249
-        }
4250
-    }
4251
-
4252
-
4253
-    /**
4254
-     * @param EEM_Base       $entity_model
4255
-     * @param Exception|null $exception
4256
-     * @param string         $action
4257
-     * @since 4.10.30.p
4258
-     */
4259
-    private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, ?Exception $exception = null)
4260
-    {
4261
-        if ($exception instanceof Exception) {
4262
-            throw new RuntimeException(
4263
-                sprintf(
4264
-                    esc_html__(
4265
-                        'Could not %1$s the %2$s because the following error occurred: %3$s',
4266
-                        'event_espresso'
4267
-                    ),
4268
-                    $action,
4269
-                    $entity_model->get_this_model_name(),
4270
-                    $exception->getMessage()
4271
-                )
4272
-            );
4273
-        }
4274
-        throw new RuntimeException(
4275
-            sprintf(
4276
-                esc_html__(
4277
-                    'Could not %1$s the %2$s because an invalid ID was received.',
4278
-                    'event_espresso'
4279
-                ),
4280
-                $action,
4281
-                $entity_model->get_this_model_name()
4282
-            )
4283
-        );
4284
-    }
3317
+		// add nonce
3318
+		$nonce                                             =
3319
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3320
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3321
+		// add REQUIRED form action
3322
+		$hidden_fields = [
3323
+			'action' => ['type' => 'hidden', 'value' => $route],
3324
+		];
3325
+		// merge arrays
3326
+		$hidden_fields = is_array($additional_hidden_fields)
3327
+			? array_merge($hidden_fields, $additional_hidden_fields)
3328
+			: $hidden_fields;
3329
+		// generate form fields
3330
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3331
+		// add fields to form
3332
+		foreach ((array) $form_fields as $form_field) {
3333
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3334
+		}
3335
+		// close form
3336
+		$this->_template_args['after_admin_page_content'] = '</form>';
3337
+	}
3338
+
3339
+
3340
+	/**
3341
+	 * Public Wrapper for _redirect_after_action() method since its
3342
+	 * discovered it would be useful for external code to have access.
3343
+	 *
3344
+	 * @param bool   $success
3345
+	 * @param string $what
3346
+	 * @param string $action_desc
3347
+	 * @param array  $query_args
3348
+	 * @param bool   $override_overwrite
3349
+	 * @throws EE_Error
3350
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3351
+	 * @since 4.5.0
3352
+	 */
3353
+	public function redirect_after_action(
3354
+		$success = false,
3355
+		$what = 'item',
3356
+		$action_desc = 'processed',
3357
+		$query_args = [],
3358
+		$override_overwrite = false
3359
+	) {
3360
+		$this->_redirect_after_action(
3361
+			$success,
3362
+			$what,
3363
+			$action_desc,
3364
+			$query_args,
3365
+			$override_overwrite
3366
+		);
3367
+	}
3368
+
3369
+
3370
+	/**
3371
+	 * Helper method for merging existing request data with the returned redirect url.
3372
+	 *
3373
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3374
+	 * filters are still applied.
3375
+	 *
3376
+	 * @param array $new_route_data
3377
+	 * @return array
3378
+	 */
3379
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3380
+	{
3381
+		foreach ($this->request->requestParams() as $ref => $value) {
3382
+			// unset nonces
3383
+			if (strpos($ref, 'nonce') !== false) {
3384
+				$this->request->unSetRequestParam($ref);
3385
+				continue;
3386
+			}
3387
+			// urlencode values.
3388
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3389
+			$this->request->setRequestParam($ref, $value);
3390
+		}
3391
+		return array_merge($this->request->requestParams(), $new_route_data);
3392
+	}
3393
+
3394
+
3395
+	/**
3396
+	 * @param int|float|string $success      - whether success was for two or more records, or just one, or none
3397
+	 * @param string           $what         - what the action was performed on
3398
+	 * @param string           $action_desc  - what was done ie: updated, deleted, etc
3399
+	 * @param array $query_args              - an array of query_args to be added to the URL to redirect to
3400
+	 * @param BOOL $override_overwrite       - by default all EE_Error::success messages are overwritten,
3401
+	 *                                         this allows you to override this so that they show.
3402
+	 * @return void
3403
+	 * @throws EE_Error
3404
+	 * @throws InvalidArgumentException
3405
+	 * @throws InvalidDataTypeException
3406
+	 * @throws InvalidInterfaceException
3407
+	 */
3408
+	protected function _redirect_after_action(
3409
+		$success = 0,
3410
+		string $what = 'item',
3411
+		string $action_desc = 'processed',
3412
+		array $query_args = [],
3413
+		bool $override_overwrite = false
3414
+	) {
3415
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3416
+		$notices      = EE_Error::get_notices(false);
3417
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3418
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3419
+			EE_Error::overwrite_success();
3420
+		}
3421
+		if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3422
+			// how many records affected ? more than one record ? or just one ?
3423
+			EE_Error::add_success(
3424
+				sprintf(
3425
+					esc_html(
3426
+						_n(
3427
+							'The "%1$s" has been successfully %2$s.',
3428
+							'The "%1$s" have been successfully %2$s.',
3429
+							$success,
3430
+							'event_espresso'
3431
+						)
3432
+					),
3433
+					$what,
3434
+					$action_desc
3435
+				),
3436
+				__FILE__,
3437
+				__FUNCTION__,
3438
+				__LINE__
3439
+			);
3440
+		}
3441
+		// check that $query_args isn't something crazy
3442
+		if (! is_array($query_args)) {
3443
+			$query_args = [];
3444
+		}
3445
+		/**
3446
+		 * Allow injecting actions before the query_args are modified for possible different
3447
+		 * redirections on save and close actions
3448
+		 *
3449
+		 * @param array $query_args       The original query_args array coming into the
3450
+		 *                                method.
3451
+		 * @since 4.2.0
3452
+		 */
3453
+		do_action(
3454
+			"AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3455
+			$query_args
3456
+		);
3457
+		// set redirect url.
3458
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3459
+		// otherwise we go with whatever is set as the _admin_base_url
3460
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3461
+		// calculate where we're going (if we have a "save and close" button pushed)
3462
+		if (
3463
+			$this->request->requestParamIsSet('save_and_close')
3464
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3465
+		) {
3466
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3467
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3468
+			// regenerate query args array from referrer URL
3469
+			parse_str($parsed_url['query'], $query_args);
3470
+			// correct page and action will be in the query args now
3471
+			$redirect_url = admin_url('admin.php');
3472
+		}
3473
+		// merge any default query_args set in _default_route_query_args property
3474
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3475
+			$args_to_merge = [];
3476
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3477
+				// is there a wp_referer array in our _default_route_query_args property?
3478
+				if ($query_param === 'wp_referer') {
3479
+					$query_value = (array) $query_value;
3480
+					foreach ($query_value as $reference => $value) {
3481
+						if (strpos($reference, 'nonce') !== false) {
3482
+							continue;
3483
+						}
3484
+						// finally we will override any arguments in the referer with
3485
+						// what might be set on the _default_route_query_args array.
3486
+						if (isset($this->_default_route_query_args[ $reference ])) {
3487
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3488
+						} else {
3489
+							$args_to_merge[ $reference ] = urlencode($value);
3490
+						}
3491
+					}
3492
+					continue;
3493
+				}
3494
+				$args_to_merge[ $query_param ] = $query_value;
3495
+			}
3496
+			// now let's merge these arguments but override with what was specifically sent in to the
3497
+			// redirect.
3498
+			$query_args = array_merge($args_to_merge, $query_args);
3499
+		}
3500
+		$this->_process_notices($query_args);
3501
+		// generate redirect url
3502
+		// if redirecting to anything other than the main page, add a nonce
3503
+		if (isset($query_args['action'])) {
3504
+			// manually generate wp_nonce and merge that with the query vars
3505
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3506
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3507
+		}
3508
+		// we're adding some hooks and filters in here for processing any things just before redirects
3509
+		// (example: an admin page has done an insert or update and we want to run something after that).
3510
+		do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3511
+		$redirect_url = apply_filters(
3512
+			'FHEE_redirect_' . $this->class_name . $this->_req_action,
3513
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3514
+			$query_args
3515
+		);
3516
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3517
+		if ($this->request->isAjax()) {
3518
+			$default_data                    = [
3519
+				'close'        => true,
3520
+				'redirect_url' => $redirect_url,
3521
+				'where'        => 'main',
3522
+				'what'         => 'append',
3523
+			];
3524
+			$this->_template_args['success'] = $success;
3525
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3526
+				$default_data,
3527
+				$this->_template_args['data']
3528
+			) : $default_data;
3529
+			$this->_return_json();
3530
+		}
3531
+		wp_safe_redirect($redirect_url);
3532
+		exit();
3533
+	}
3534
+
3535
+
3536
+	/**
3537
+	 * process any notices before redirecting (or returning ajax request)
3538
+	 * This method sets the $this->_template_args['notices'] attribute;
3539
+	 *
3540
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3541
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3542
+	 *                                  page_routes haven't been defined yet.
3543
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3544
+	 *                                  still save a transient for the notice.
3545
+	 * @return void
3546
+	 * @throws EE_Error
3547
+	 * @throws InvalidArgumentException
3548
+	 * @throws InvalidDataTypeException
3549
+	 * @throws InvalidInterfaceException
3550
+	 */
3551
+	protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3552
+	{
3553
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3554
+		if ($this->request->isAjax()) {
3555
+			$notices = EE_Error::get_notices(false);
3556
+			if (empty($this->_template_args['success'])) {
3557
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3558
+			}
3559
+			if (empty($this->_template_args['errors'])) {
3560
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3561
+			}
3562
+			if (empty($this->_template_args['attention'])) {
3563
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3564
+			}
3565
+		}
3566
+		$this->_template_args['notices'] = EE_Error::get_notices();
3567
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3568
+		if (! $this->request->isAjax() || $sticky_notices) {
3569
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3570
+			$this->_add_transient(
3571
+				$route,
3572
+				$this->_template_args['notices'],
3573
+				true,
3574
+				$skip_route_verify
3575
+			);
3576
+		}
3577
+	}
3578
+
3579
+
3580
+	/**
3581
+	 * get_action_link_or_button
3582
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3583
+	 *
3584
+	 * @param string $action        use this to indicate which action the url is generated with.
3585
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3586
+	 *                              property.
3587
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3588
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3589
+	 * @param string $base_url      If this is not provided
3590
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3591
+	 *                              Otherwise this value will be used.
3592
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3593
+	 * @return string
3594
+	 * @throws InvalidArgumentException
3595
+	 * @throws InvalidInterfaceException
3596
+	 * @throws InvalidDataTypeException
3597
+	 * @throws EE_Error
3598
+	 */
3599
+	public function get_action_link_or_button(
3600
+		$action,
3601
+		$type = 'add',
3602
+		$extra_request = [],
3603
+		$class = 'button--primary',
3604
+		$base_url = '',
3605
+		$exclude_nonce = false
3606
+	) {
3607
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3608
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3609
+			throw new EE_Error(
3610
+				sprintf(
3611
+					esc_html__(
3612
+						'There is no page route for given action for the button.  This action was given: %s',
3613
+						'event_espresso'
3614
+					),
3615
+					$action
3616
+				)
3617
+			);
3618
+		}
3619
+		if (! isset($this->_labels['buttons'][ $type ])) {
3620
+			throw new EE_Error(
3621
+				sprintf(
3622
+					esc_html__(
3623
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3624
+						'event_espresso'
3625
+					),
3626
+					$type
3627
+				)
3628
+			);
3629
+		}
3630
+		// finally check user access for this button.
3631
+		$has_access = $this->check_user_access($action, true);
3632
+		if (! $has_access) {
3633
+			return '';
3634
+		}
3635
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3636
+		$query_args = [
3637
+			'action' => $action,
3638
+		];
3639
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3640
+		if (! empty($extra_request)) {
3641
+			$query_args = array_merge($extra_request, $query_args);
3642
+		}
3643
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3644
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3645
+	}
3646
+
3647
+
3648
+	/**
3649
+	 * _per_page_screen_option
3650
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3651
+	 *
3652
+	 * @return void
3653
+	 * @throws InvalidArgumentException
3654
+	 * @throws InvalidInterfaceException
3655
+	 * @throws InvalidDataTypeException
3656
+	 */
3657
+	protected function _per_page_screen_option()
3658
+	{
3659
+		$option = 'per_page';
3660
+		$args   = [
3661
+			'label'   => apply_filters(
3662
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3663
+				$this->_admin_page_title,
3664
+				$this
3665
+			),
3666
+			'default' => (int) apply_filters(
3667
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3668
+				20
3669
+			),
3670
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3671
+		];
3672
+		// ONLY add the screen option if the user has access to it.
3673
+		if ($this->check_user_access($this->_current_view, true)) {
3674
+			add_screen_option($option, $args);
3675
+		}
3676
+	}
3677
+
3678
+
3679
+	/**
3680
+	 * set_per_page_screen_option
3681
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3682
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3683
+	 * admin_menu.
3684
+	 *
3685
+	 * @return void
3686
+	 */
3687
+	private function _set_per_page_screen_options()
3688
+	{
3689
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3690
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3691
+			if (! $user = wp_get_current_user()) {
3692
+				return;
3693
+			}
3694
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3695
+			if (! $option) {
3696
+				return;
3697
+			}
3698
+			$value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3699
+			$map_option = $option;
3700
+			$option     = str_replace('-', '_', $option);
3701
+			switch ($map_option) {
3702
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3703
+					$max_value = apply_filters(
3704
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3705
+						999,
3706
+						$this->_current_page,
3707
+						$this->_current_view
3708
+					);
3709
+					if ($value < 1) {
3710
+						return;
3711
+					}
3712
+					$value = min($value, $max_value);
3713
+					break;
3714
+				default:
3715
+					$value = apply_filters(
3716
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3717
+						false,
3718
+						$option,
3719
+						$value
3720
+					);
3721
+					if (false === $value) {
3722
+						return;
3723
+					}
3724
+					break;
3725
+			}
3726
+			update_user_meta($user->ID, $option, $value);
3727
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3728
+			exit;
3729
+		}
3730
+	}
3731
+
3732
+
3733
+	/**
3734
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3735
+	 *
3736
+	 * @param array $data array that will be assigned to template args.
3737
+	 */
3738
+	public function set_template_args($data)
3739
+	{
3740
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3741
+	}
3742
+
3743
+
3744
+	/**
3745
+	 * This makes available the WP transient system for temporarily moving data between routes
3746
+	 *
3747
+	 * @param string $route             the route that should receive the transient
3748
+	 * @param array  $data              the data that gets sent
3749
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3750
+	 *                                  normal route transient.
3751
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3752
+	 *                                  when we are adding a transient before page_routes have been defined.
3753
+	 * @return void
3754
+	 * @throws EE_Error
3755
+	 */
3756
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3757
+	{
3758
+		$user_id = get_current_user_id();
3759
+		if (! $skip_route_verify) {
3760
+			$this->_verify_route($route);
3761
+		}
3762
+		// now let's set the string for what kind of transient we're setting
3763
+		$transient = $notices
3764
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3765
+			: 'rte_tx_' . $route . '_' . $user_id;
3766
+		$data      = $notices ? ['notices' => $data] : $data;
3767
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3768
+		$existing = is_multisite() && is_network_admin()
3769
+			? get_site_transient($transient)
3770
+			: get_transient($transient);
3771
+		if ($existing) {
3772
+			$data = array_merge((array) $data, (array) $existing);
3773
+		}
3774
+		if (is_multisite() && is_network_admin()) {
3775
+			set_site_transient($transient, $data, 8);
3776
+		} else {
3777
+			set_transient($transient, $data, 8);
3778
+		}
3779
+	}
3780
+
3781
+
3782
+	/**
3783
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3784
+	 *
3785
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3786
+	 * @param string $route
3787
+	 * @return mixed data
3788
+	 */
3789
+	protected function _get_transient($notices = false, $route = '')
3790
+	{
3791
+		$user_id   = get_current_user_id();
3792
+		$route     = ! $route ? $this->_req_action : $route;
3793
+		$transient = $notices
3794
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3795
+			: 'rte_tx_' . $route . '_' . $user_id;
3796
+		$data      = is_multisite() && is_network_admin()
3797
+			? get_site_transient($transient)
3798
+			: get_transient($transient);
3799
+		// delete transient after retrieval (just in case it hasn't expired);
3800
+		if (is_multisite() && is_network_admin()) {
3801
+			delete_site_transient($transient);
3802
+		} else {
3803
+			delete_transient($transient);
3804
+		}
3805
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3806
+	}
3807
+
3808
+
3809
+	/**
3810
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3811
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3812
+	 * default route callback on the EE_Admin page you want it run.)
3813
+	 *
3814
+	 * @return void
3815
+	 */
3816
+	protected function _transient_garbage_collection()
3817
+	{
3818
+		global $wpdb;
3819
+		// retrieve all existing transients
3820
+		$query =
3821
+			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3822
+		if ($results = $wpdb->get_results($query)) {
3823
+			foreach ($results as $result) {
3824
+				$transient = str_replace('_transient_', '', $result->option_name);
3825
+				get_transient($transient);
3826
+				if (is_multisite() && is_network_admin()) {
3827
+					get_site_transient($transient);
3828
+				}
3829
+			}
3830
+		}
3831
+	}
3832
+
3833
+
3834
+	/**
3835
+	 * get_view
3836
+	 *
3837
+	 * @return string content of _view property
3838
+	 */
3839
+	public function get_view()
3840
+	{
3841
+		return $this->_view;
3842
+	}
3843
+
3844
+
3845
+	/**
3846
+	 * getter for the protected $_views property
3847
+	 *
3848
+	 * @return array
3849
+	 */
3850
+	public function get_views()
3851
+	{
3852
+		return $this->_views;
3853
+	}
3854
+
3855
+
3856
+	/**
3857
+	 * get_current_page
3858
+	 *
3859
+	 * @return string _current_page property value
3860
+	 */
3861
+	public function get_current_page()
3862
+	{
3863
+		return $this->_current_page;
3864
+	}
3865
+
3866
+
3867
+	/**
3868
+	 * get_current_view
3869
+	 *
3870
+	 * @return string _current_view property value
3871
+	 */
3872
+	public function get_current_view()
3873
+	{
3874
+		return $this->_current_view;
3875
+	}
3876
+
3877
+
3878
+	/**
3879
+	 * get_current_screen
3880
+	 *
3881
+	 * @return object The current WP_Screen object
3882
+	 */
3883
+	public function get_current_screen()
3884
+	{
3885
+		return $this->_current_screen;
3886
+	}
3887
+
3888
+
3889
+	/**
3890
+	 * get_current_page_view_url
3891
+	 *
3892
+	 * @return string This returns the url for the current_page_view.
3893
+	 */
3894
+	public function get_current_page_view_url()
3895
+	{
3896
+		return $this->_current_page_view_url;
3897
+	}
3898
+
3899
+
3900
+	/**
3901
+	 * just returns the Request
3902
+	 *
3903
+	 * @return RequestInterface
3904
+	 */
3905
+	public function get_request()
3906
+	{
3907
+		return $this->request;
3908
+	}
3909
+
3910
+
3911
+	/**
3912
+	 * just returns the _req_data property
3913
+	 *
3914
+	 * @return array
3915
+	 */
3916
+	public function get_request_data()
3917
+	{
3918
+		return $this->request->requestParams();
3919
+	}
3920
+
3921
+
3922
+	/**
3923
+	 * returns the _req_data protected property
3924
+	 *
3925
+	 * @return string
3926
+	 */
3927
+	public function get_req_action()
3928
+	{
3929
+		return $this->_req_action;
3930
+	}
3931
+
3932
+
3933
+	/**
3934
+	 * @return bool  value of $_is_caf property
3935
+	 */
3936
+	public function is_caf()
3937
+	{
3938
+		return $this->_is_caf;
3939
+	}
3940
+
3941
+
3942
+	/**
3943
+	 * @return mixed
3944
+	 */
3945
+	public function default_espresso_metaboxes()
3946
+	{
3947
+		return $this->_default_espresso_metaboxes;
3948
+	}
3949
+
3950
+
3951
+	/**
3952
+	 * @return mixed
3953
+	 */
3954
+	public function admin_base_url()
3955
+	{
3956
+		return $this->_admin_base_url;
3957
+	}
3958
+
3959
+
3960
+	/**
3961
+	 * @return mixed
3962
+	 */
3963
+	public function wp_page_slug()
3964
+	{
3965
+		return $this->_wp_page_slug;
3966
+	}
3967
+
3968
+
3969
+	/**
3970
+	 * updates  espresso configuration settings
3971
+	 *
3972
+	 * @param string                   $tab
3973
+	 * @param EE_Config_Base|EE_Config $config
3974
+	 * @param string                   $file file where error occurred
3975
+	 * @param string                   $func function  where error occurred
3976
+	 * @param string                   $line line no where error occurred
3977
+	 * @return boolean
3978
+	 */
3979
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3980
+	{
3981
+		// remove any options that are NOT going to be saved with the config settings.
3982
+		if (isset($config->core->ee_ueip_optin)) {
3983
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
3984
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3985
+			update_option('ee_ueip_has_notified', true);
3986
+		}
3987
+		// and save it (note we're also doing the network save here)
3988
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
3989
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
3990
+		if ($config_saved && $net_saved) {
3991
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3992
+			return true;
3993
+		}
3994
+		EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3995
+		return false;
3996
+	}
3997
+
3998
+
3999
+	/**
4000
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4001
+	 *
4002
+	 * @return array
4003
+	 */
4004
+	public function get_yes_no_values()
4005
+	{
4006
+		return $this->_yes_no_values;
4007
+	}
4008
+
4009
+
4010
+	/**
4011
+	 * @return string
4012
+	 * @throws ReflectionException
4013
+	 * @since $VID:$
4014
+	 */
4015
+	protected function _get_dir()
4016
+	{
4017
+		$reflector = new ReflectionClass($this->class_name);
4018
+		return dirname($reflector->getFileName());
4019
+	}
4020
+
4021
+
4022
+	/**
4023
+	 * A helper for getting a "next link".
4024
+	 *
4025
+	 * @param string $url   The url to link to
4026
+	 * @param string $class The class to use.
4027
+	 * @return string
4028
+	 */
4029
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4030
+	{
4031
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4032
+	}
4033
+
4034
+
4035
+	/**
4036
+	 * A helper for getting a "previous link".
4037
+	 *
4038
+	 * @param string $url   The url to link to
4039
+	 * @param string $class The class to use.
4040
+	 * @return string
4041
+	 */
4042
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4043
+	{
4044
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4045
+	}
4046
+
4047
+
4048
+
4049
+
4050
+
4051
+
4052
+
4053
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4054
+
4055
+
4056
+	/**
4057
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4058
+	 * 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
4059
+	 * _req_data array.
4060
+	 *
4061
+	 * @return bool success/fail
4062
+	 * @throws EE_Error
4063
+	 * @throws InvalidArgumentException
4064
+	 * @throws ReflectionException
4065
+	 * @throws InvalidDataTypeException
4066
+	 * @throws InvalidInterfaceException
4067
+	 */
4068
+	protected function _process_resend_registration()
4069
+	{
4070
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4071
+		do_action(
4072
+			'AHEE__EE_Admin_Page___process_resend_registration',
4073
+			$this->_template_args['success'],
4074
+			$this->request->requestParams()
4075
+		);
4076
+		return $this->_template_args['success'];
4077
+	}
4078
+
4079
+
4080
+	/**
4081
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4082
+	 *
4083
+	 * @param EE_Payment $payment
4084
+	 * @return bool success/fail
4085
+	 */
4086
+	protected function _process_payment_notification(EE_Payment $payment)
4087
+	{
4088
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4089
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4090
+		$this->_template_args['success'] = apply_filters(
4091
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4092
+			false,
4093
+			$payment
4094
+		);
4095
+		return $this->_template_args['success'];
4096
+	}
4097
+
4098
+
4099
+	/**
4100
+	 * @param EEM_Base      $entity_model
4101
+	 * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4102
+	 * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4103
+	 * @param string        $delete_column  name of the field that denotes whether entity is trashed
4104
+	 * @param callable|null $callback       called after entity is trashed, restored, or deleted
4105
+	 * @return int|float
4106
+	 * @throws EE_Error
4107
+	 */
4108
+	protected function trashRestoreDeleteEntities(
4109
+		EEM_Base $entity_model,
4110
+		string $entity_PK_name,
4111
+		string $action = EE_Admin_List_Table::ACTION_DELETE,
4112
+		string $delete_column = '',
4113
+		callable $callback = null
4114
+	) {
4115
+		$entity_PK      = $entity_model->get_primary_key_field();
4116
+		$entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4117
+		$entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4118
+		// grab ID if deleting a single entity
4119
+		if ($this->request->requestParamIsSet($entity_PK_name)) {
4120
+			$ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4121
+			return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4122
+		}
4123
+		// or grab checkbox array if bulk deleting
4124
+		$checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4125
+		if (empty($checkboxes)) {
4126
+			return 0;
4127
+		}
4128
+		$success = 0;
4129
+		$IDs     = array_keys($checkboxes);
4130
+		// cycle thru bulk action checkboxes
4131
+		foreach ($IDs as $ID) {
4132
+			// increment $success
4133
+			if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4134
+				$success++;
4135
+			}
4136
+		}
4137
+		$count = (int) count($checkboxes);
4138
+		// if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4139
+		// otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4140
+		return $success === $count ? $count : $success / $count;
4141
+	}
4142
+
4143
+
4144
+	/**
4145
+	 * @param EE_Primary_Key_Field_Base $entity_PK
4146
+	 * @return string
4147
+	 * @throws EE_Error
4148
+	 * @since   4.10.30.p
4149
+	 */
4150
+	private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4151
+	{
4152
+		$entity_PK_type = $entity_PK->getSchemaType();
4153
+		switch ($entity_PK_type) {
4154
+			case 'boolean':
4155
+				return 'bool';
4156
+			case 'integer':
4157
+				return 'int';
4158
+			case 'number':
4159
+				return 'float';
4160
+			case 'string':
4161
+				return 'string';
4162
+		}
4163
+		throw new RuntimeException(
4164
+			sprintf(
4165
+				esc_html__(
4166
+					'"%1$s" is an invalid schema type for the %2$s primary key.',
4167
+					'event_espresso'
4168
+				),
4169
+				$entity_PK_type,
4170
+				$entity_PK->get_name()
4171
+			)
4172
+		);
4173
+	}
4174
+
4175
+
4176
+	/**
4177
+	 * @param EEM_Base      $entity_model
4178
+	 * @param int|string    $entity_ID
4179
+	 * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4180
+	 * @param string        $delete_column name of the field that denotes whether entity is trashed
4181
+	 * @param callable|null $callback      called after entity is trashed, restored, or deleted
4182
+	 * @return bool
4183
+	 */
4184
+	protected function trashRestoreDeleteEntity(
4185
+		EEM_Base $entity_model,
4186
+		$entity_ID,
4187
+		string $action,
4188
+		string $delete_column,
4189
+		?callable $callback = null
4190
+	): bool {
4191
+		$entity_ID = absint($entity_ID);
4192
+		if (! $entity_ID) {
4193
+			$this->trashRestoreDeleteError($action, $entity_model);
4194
+		}
4195
+		$result = 0;
4196
+		try {
4197
+			switch ($action) {
4198
+				case EE_Admin_List_Table::ACTION_DELETE:
4199
+					$result = (bool) $entity_model->delete_permanently_by_ID($entity_ID);
4200
+					break;
4201
+				case EE_Admin_List_Table::ACTION_RESTORE:
4202
+					$this->validateDeleteColumn($entity_model, $delete_column);
4203
+					$result = $entity_model->update_by_ID([$delete_column => 0], $entity_ID);
4204
+					break;
4205
+				case EE_Admin_List_Table::ACTION_TRASH:
4206
+					$this->validateDeleteColumn($entity_model, $delete_column);
4207
+					$result = $entity_model->update_by_ID([$delete_column => 1], $entity_ID);
4208
+					break;
4209
+			}
4210
+		} catch (Exception $exception) {
4211
+			$this->trashRestoreDeleteError($action, $entity_model, $exception);
4212
+		}
4213
+		if (is_callable($callback)) {
4214
+			call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4215
+		}
4216
+		return $result;
4217
+	}
4218
+
4219
+
4220
+	/**
4221
+	 * @param EEM_Base $entity_model
4222
+	 * @param string   $delete_column
4223
+	 * @since 4.10.30.p
4224
+	 */
4225
+	private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4226
+	{
4227
+		if (empty($delete_column)) {
4228
+			throw new DomainException(
4229
+				sprintf(
4230
+					esc_html__(
4231
+						'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4232
+						'event_espresso'
4233
+					),
4234
+					$entity_model->get_this_model_name()
4235
+				)
4236
+			);
4237
+		}
4238
+		if (! $entity_model->has_field($delete_column)) {
4239
+			throw new DomainException(
4240
+				sprintf(
4241
+					esc_html__(
4242
+						'The %1$s field does not exist on the %2$s model.',
4243
+						'event_espresso'
4244
+					),
4245
+					$delete_column,
4246
+					$entity_model->get_this_model_name()
4247
+				)
4248
+			);
4249
+		}
4250
+	}
4251
+
4252
+
4253
+	/**
4254
+	 * @param EEM_Base       $entity_model
4255
+	 * @param Exception|null $exception
4256
+	 * @param string         $action
4257
+	 * @since 4.10.30.p
4258
+	 */
4259
+	private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, ?Exception $exception = null)
4260
+	{
4261
+		if ($exception instanceof Exception) {
4262
+			throw new RuntimeException(
4263
+				sprintf(
4264
+					esc_html__(
4265
+						'Could not %1$s the %2$s because the following error occurred: %3$s',
4266
+						'event_espresso'
4267
+					),
4268
+					$action,
4269
+					$entity_model->get_this_model_name(),
4270
+					$exception->getMessage()
4271
+				)
4272
+			);
4273
+		}
4274
+		throw new RuntimeException(
4275
+			sprintf(
4276
+				esc_html__(
4277
+					'Could not %1$s the %2$s because an invalid ID was received.',
4278
+					'event_espresso'
4279
+				),
4280
+				$action,
4281
+				$entity_model->get_this_model_name()
4282
+			)
4283
+		);
4284
+	}
4285 4285
 }
Please login to merge, or discard this patch.
Spacing   +176 added lines, -176 removed lines patch added patch discarded remove patch
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
         $ee_menu_slugs = (array) $ee_menu_slugs;
630 630
         if (
631 631
             ! $this->request->isAjax()
632
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
632
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
633 633
         ) {
634 634
             return;
635 635
         }
@@ -649,7 +649,7 @@  discard block
 block discarded – undo
649 649
             : $req_action;
650 650
 
651 651
         $this->_current_view = $this->_req_action;
652
-        $this->_req_nonce    = $this->_req_action . '_nonce';
652
+        $this->_req_nonce    = $this->_req_action.'_nonce';
653 653
         $this->_define_page_props();
654 654
         $this->_current_page_view_url = add_query_arg(
655 655
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -679,33 +679,33 @@  discard block
 block discarded – undo
679 679
         }
680 680
         // filter routes and page_config so addons can add their stuff. Filtering done per class
681 681
         $this->_page_routes = apply_filters(
682
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
682
+            'FHEE__'.$this->class_name.'__page_setup__page_routes',
683 683
             $this->_page_routes,
684 684
             $this
685 685
         );
686 686
         $this->_page_config = apply_filters(
687
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
687
+            'FHEE__'.$this->class_name.'__page_setup__page_config',
688 688
             $this->_page_config,
689 689
             $this
690 690
         );
691 691
         if ($this->base_class_name !== '') {
692 692
             $this->_page_routes = apply_filters(
693
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
693
+                'FHEE__'.$this->base_class_name.'__page_setup__page_routes',
694 694
                 $this->_page_routes,
695 695
                 $this
696 696
             );
697 697
             $this->_page_config = apply_filters(
698
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
698
+                'FHEE__'.$this->base_class_name.'__page_setup__page_config',
699 699
                 $this->_page_config,
700 700
                 $this
701 701
             );
702 702
         }
703 703
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
704 704
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
705
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
705
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
706 706
             add_action(
707 707
                 'AHEE__EE_Admin_Page__route_admin_request',
708
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
708
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
709 709
                 10,
710 710
                 2
711 711
             );
@@ -718,8 +718,8 @@  discard block
 block discarded – undo
718 718
             if ($this->_is_UI_request) {
719 719
                 // admin_init stuff - global, all views for this page class, specific view
720 720
                 add_action('admin_init', [$this, 'admin_init'], 10);
721
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
722
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
721
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
722
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
723 723
                 }
724 724
             } else {
725 725
                 // hijack regular WP loading and route admin request immediately
@@ -738,12 +738,12 @@  discard block
 block discarded – undo
738 738
      */
739 739
     private function _do_other_page_hooks()
740 740
     {
741
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
741
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
742 742
         foreach ($registered_pages as $page) {
743 743
             // now let's setup the file name and class that should be present
744 744
             $classname = str_replace('.class.php', '', $page);
745 745
             // autoloaders should take care of loading file
746
-            if (! class_exists($classname)) {
746
+            if ( ! class_exists($classname)) {
747 747
                 $error_msg[] = sprintf(
748 748
                     esc_html__(
749 749
                         'Something went wrong with loading the %s admin hooks page.',
@@ -760,7 +760,7 @@  discard block
 block discarded – undo
760 760
                                    ),
761 761
                                    $page,
762 762
                                    '<br />',
763
-                                   '<strong>' . $classname . '</strong>'
763
+                                   '<strong>'.$classname.'</strong>'
764 764
                                );
765 765
                 throw new EE_Error(implode('||', $error_msg));
766 766
             }
@@ -802,13 +802,13 @@  discard block
 block discarded – undo
802 802
         // load admin_notices - global, page class, and view specific
803 803
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
804 804
         add_action('admin_notices', [$this, 'admin_notices'], 10);
805
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
806
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
805
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
806
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
807 807
         }
808 808
         // load network admin_notices - global, page class, and view specific
809 809
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
810
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
811
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
810
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
811
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
812 812
         }
813 813
         // this will save any per_page screen options if they are present
814 814
         $this->_set_per_page_screen_options();
@@ -929,7 +929,7 @@  discard block
 block discarded – undo
929 929
     protected function _verify_routes()
930 930
     {
931 931
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
932
-        if (! $this->_current_page && ! $this->request->isAjax()) {
932
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
933 933
             return false;
934 934
         }
935 935
         $this->_route = false;
@@ -941,7 +941,7 @@  discard block
 block discarded – undo
941 941
                 $this->_admin_page_title
942 942
             );
943 943
             // developer error msg
944
-            $error_msg .= '||' . $error_msg
944
+            $error_msg .= '||'.$error_msg
945 945
                           . esc_html__(
946 946
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
947 947
                               'event_espresso'
@@ -950,8 +950,8 @@  discard block
 block discarded – undo
950 950
         }
951 951
         // and that the requested page route exists
952 952
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
953
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
954
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
953
+            $this->_route        = $this->_page_routes[$this->_req_action];
954
+            $this->_route_config = $this->_page_config[$this->_req_action] ?? [];
955 955
         } else {
956 956
             // user error msg
957 957
             $error_msg = sprintf(
@@ -962,7 +962,7 @@  discard block
 block discarded – undo
962 962
                 $this->_admin_page_title
963 963
             );
964 964
             // developer error msg
965
-            $error_msg .= '||' . $error_msg
965
+            $error_msg .= '||'.$error_msg
966 966
                           . sprintf(
967 967
                               esc_html__(
968 968
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
             throw new EE_Error($error_msg);
974 974
         }
975 975
         // and that a default route exists
976
-        if (! array_key_exists('default', $this->_page_routes)) {
976
+        if ( ! array_key_exists('default', $this->_page_routes)) {
977 977
             // user error msg
978 978
             $error_msg = sprintf(
979 979
                 esc_html__(
@@ -983,7 +983,7 @@  discard block
 block discarded – undo
983 983
                 $this->_admin_page_title
984 984
             );
985 985
             // developer error msg
986
-            $error_msg .= '||' . $error_msg
986
+            $error_msg .= '||'.$error_msg
987 987
                           . esc_html__(
988 988
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
989 989
                               'event_espresso'
@@ -1025,7 +1025,7 @@  discard block
 block discarded – undo
1025 1025
             $this->_admin_page_title
1026 1026
         );
1027 1027
         // developer error msg
1028
-        $error_msg .= '||' . $error_msg
1028
+        $error_msg .= '||'.$error_msg
1029 1029
                       . sprintf(
1030 1030
                           esc_html__(
1031 1031
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -1053,7 +1053,7 @@  discard block
 block discarded – undo
1053 1053
     protected function _verify_nonce($nonce, $nonce_ref)
1054 1054
     {
1055 1055
         // verify nonce against expected value
1056
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1056
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
1057 1057
             // these are not the droids you are looking for !!!
1058 1058
             $msg = sprintf(
1059 1059
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -1070,7 +1070,7 @@  discard block
 block discarded – undo
1070 1070
                     __CLASS__
1071 1071
                 );
1072 1072
             }
1073
-            if (! $this->request->isAjax()) {
1073
+            if ( ! $this->request->isAjax()) {
1074 1074
                 wp_die($msg);
1075 1075
             }
1076 1076
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -1094,7 +1094,7 @@  discard block
 block discarded – undo
1094 1094
      */
1095 1095
     protected function _route_admin_request()
1096 1096
     {
1097
-        if (! $this->_is_UI_request) {
1097
+        if ( ! $this->_is_UI_request) {
1098 1098
             $this->_verify_routes();
1099 1099
         }
1100 1100
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
         $error_msg = '';
1115 1115
         // action right before calling route
1116 1116
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1117
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1117
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1118 1118
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1119 1119
         }
1120 1120
         // strip _wp_http_referer from the server REQUEST_URI
@@ -1126,7 +1126,7 @@  discard block
 block discarded – undo
1126 1126
         );
1127 1127
         // set new value in both our Request object and the super global
1128 1128
         $this->request->setServerParam('REQUEST_URI', $request_uri, true);
1129
-        if (! empty($func)) {
1129
+        if ( ! empty($func)) {
1130 1130
             if (is_array($func)) {
1131 1131
                 [$class, $method] = $func;
1132 1132
             } elseif (strpos($func, '::') !== false) {
@@ -1135,7 +1135,7 @@  discard block
 block discarded – undo
1135 1135
                 $class  = $this;
1136 1136
                 $method = $func;
1137 1137
             }
1138
-            if (! (is_object($class) && $class === $this)) {
1138
+            if ( ! (is_object($class) && $class === $this)) {
1139 1139
                 // send along this admin page object for access by addons.
1140 1140
                 $args['admin_page_object'] = $this;
1141 1141
             }
@@ -1176,7 +1176,7 @@  discard block
 block discarded – undo
1176 1176
                     $method
1177 1177
                 );
1178 1178
             }
1179
-            if (! empty($error_msg)) {
1179
+            if ( ! empty($error_msg)) {
1180 1180
                 throw new EE_Error($error_msg);
1181 1181
             }
1182 1182
         }
@@ -1262,7 +1262,7 @@  discard block
 block discarded – undo
1262 1262
                 if (strpos($key, 'nonce') !== false) {
1263 1263
                     continue;
1264 1264
                 }
1265
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1265
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1266 1266
             }
1267 1267
         }
1268 1268
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1302,12 +1302,12 @@  discard block
 block discarded – undo
1302 1302
      */
1303 1303
     protected function _add_help_tabs()
1304 1304
     {
1305
-        if (isset($this->_page_config[ $this->_req_action ])) {
1306
-            $config = $this->_page_config[ $this->_req_action ];
1305
+        if (isset($this->_page_config[$this->_req_action])) {
1306
+            $config = $this->_page_config[$this->_req_action];
1307 1307
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1308 1308
             if (is_array($config) && isset($config['help_sidebar'])) {
1309 1309
                 // check that the callback given is valid
1310
-                if (! method_exists($this, $config['help_sidebar'])) {
1310
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1311 1311
                     throw new EE_Error(
1312 1312
                         sprintf(
1313 1313
                             esc_html__(
@@ -1320,18 +1320,18 @@  discard block
 block discarded – undo
1320 1320
                     );
1321 1321
                 }
1322 1322
                 $content = apply_filters(
1323
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1323
+                    'FHEE__'.$this->class_name.'__add_help_tabs__help_sidebar',
1324 1324
                     $this->{$config['help_sidebar']}()
1325 1325
                 );
1326 1326
                 $this->_current_screen->set_help_sidebar($content);
1327 1327
             }
1328
-            if (! isset($config['help_tabs'])) {
1328
+            if ( ! isset($config['help_tabs'])) {
1329 1329
                 return;
1330 1330
             } //no help tabs for this route
1331 1331
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1332 1332
                 // we're here so there ARE help tabs!
1333 1333
                 // make sure we've got what we need
1334
-                if (! isset($cfg['title'])) {
1334
+                if ( ! isset($cfg['title'])) {
1335 1335
                     throw new EE_Error(
1336 1336
                         esc_html__(
1337 1337
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1339,7 +1339,7 @@  discard block
 block discarded – undo
1339 1339
                         )
1340 1340
                     );
1341 1341
                 }
1342
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1342
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1343 1343
                     throw new EE_Error(
1344 1344
                         esc_html__(
1345 1345
                             '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',
@@ -1348,11 +1348,11 @@  discard block
 block discarded – undo
1348 1348
                     );
1349 1349
                 }
1350 1350
                 // first priority goes to content.
1351
-                if (! empty($cfg['content'])) {
1351
+                if ( ! empty($cfg['content'])) {
1352 1352
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1353 1353
                     // second priority goes to filename
1354
-                } elseif (! empty($cfg['filename'])) {
1355
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1354
+                } elseif ( ! empty($cfg['filename'])) {
1355
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1356 1356
                     // 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)
1357 1357
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1358 1358
                                                              . basename($this->_get_dir())
@@ -1360,7 +1360,7 @@  discard block
 block discarded – undo
1360 1360
                                                              . $cfg['filename']
1361 1361
                                                              . '.help_tab.php' : $file_path;
1362 1362
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1363
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1363
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1364 1364
                         EE_Error::add_error(
1365 1365
                             sprintf(
1366 1366
                                 esc_html__(
@@ -1408,7 +1408,7 @@  discard block
 block discarded – undo
1408 1408
                     return;
1409 1409
                 }
1410 1410
                 // setup config array for help tab method
1411
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1411
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1412 1412
                 $_ht = [
1413 1413
                     'id'       => $id,
1414 1414
                     'title'    => $cfg['title'],
@@ -1434,8 +1434,8 @@  discard block
 block discarded – undo
1434 1434
             $qtips = (array) $this->_route_config['qtips'];
1435 1435
             // load qtip loader
1436 1436
             $path = [
1437
-                $this->_get_dir() . '/qtips/',
1438
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1437
+                $this->_get_dir().'/qtips/',
1438
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1439 1439
             ];
1440 1440
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1441 1441
         }
@@ -1457,7 +1457,7 @@  discard block
 block discarded – undo
1457 1457
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1458 1458
         $i = 0;
1459 1459
         foreach ($this->_page_config as $slug => $config) {
1460
-            if (! is_array($config) || empty($config['nav'])) {
1460
+            if ( ! is_array($config) || empty($config['nav'])) {
1461 1461
                 continue;
1462 1462
             }
1463 1463
             // no nav tab for this config
@@ -1466,12 +1466,12 @@  discard block
 block discarded – undo
1466 1466
                 // nav tab is only to appear when route requested.
1467 1467
                 continue;
1468 1468
             }
1469
-            if (! $this->check_user_access($slug, true)) {
1469
+            if ( ! $this->check_user_access($slug, true)) {
1470 1470
                 // no nav tab because current user does not have access.
1471 1471
                 continue;
1472 1472
             }
1473
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1474
-            $this->_nav_tabs[ $slug ] = [
1473
+            $css_class                = isset($config['css_class']) ? $config['css_class'].' ' : '';
1474
+            $this->_nav_tabs[$slug] = [
1475 1475
                 'url'       => isset($config['nav']['url'])
1476 1476
                     ? $config['nav']['url']
1477 1477
                     : EE_Admin_Page::add_query_args_and_nonce(
@@ -1483,14 +1483,14 @@  discard block
 block discarded – undo
1483 1483
                     : ucwords(
1484 1484
                         str_replace('_', ' ', $slug)
1485 1485
                     ),
1486
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1486
+                'css_class' => $this->_req_action === $slug ? $css_class.'nav-tab-active' : $css_class,
1487 1487
                 'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1488 1488
             ];
1489 1489
             $i++;
1490 1490
         }
1491 1491
         // if $this->_nav_tabs is empty then lets set the default
1492 1492
         if (empty($this->_nav_tabs)) {
1493
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1493
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1494 1494
                 'url'       => $this->_admin_base_url,
1495 1495
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1496 1496
                 'css_class' => 'nav-tab-active',
@@ -1515,10 +1515,10 @@  discard block
 block discarded – undo
1515 1515
             foreach ($this->_route_config['labels'] as $label => $text) {
1516 1516
                 if (is_array($text)) {
1517 1517
                     foreach ($text as $sublabel => $subtext) {
1518
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1518
+                        $this->_labels[$label][$sublabel] = $subtext;
1519 1519
                     }
1520 1520
                 } else {
1521
-                    $this->_labels[ $label ] = $text;
1521
+                    $this->_labels[$label] = $text;
1522 1522
                 }
1523 1523
             }
1524 1524
         }
@@ -1540,12 +1540,12 @@  discard block
 block discarded – undo
1540 1540
     {
1541 1541
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1542 1542
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1543
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1543
+        $capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1544 1544
                           && is_array(
1545
-                              $this->_page_routes[ $route_to_check ]
1545
+                              $this->_page_routes[$route_to_check]
1546 1546
                           )
1547
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1548
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1547
+                          && ! empty($this->_page_routes[$route_to_check]['capability'])
1548
+            ? $this->_page_routes[$route_to_check]['capability'] : null;
1549 1549
         if (empty($capability) && empty($route_to_check)) {
1550 1550
             $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1551 1551
                 : $this->_route['capability'];
@@ -1597,14 +1597,14 @@  discard block
 block discarded – undo
1597 1597
         string $priority = 'default',
1598 1598
         ?array $callback_args = null
1599 1599
     ) {
1600
-        if (! is_callable($callback)) {
1600
+        if ( ! is_callable($callback)) {
1601 1601
             return;
1602 1602
         }
1603 1603
 
1604 1604
         add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1605 1605
         add_filter(
1606 1606
             "postbox_classes_{$this->_wp_page_slug}_{$box_id}",
1607
-            function ($classes) {
1607
+            function($classes) {
1608 1608
                 array_push($classes, 'ee-admin-container');
1609 1609
                 return $classes;
1610 1610
             }
@@ -1698,7 +1698,7 @@  discard block
 block discarded – undo
1698 1698
         ';
1699 1699
 
1700 1700
         // current set timezone for timezone js
1701
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1701
+        echo '<span id="current_timezone" class="hidden">'.esc_html(EEH_DTT_Helper::get_timezone()).'</span>';
1702 1702
     }
1703 1703
 
1704 1704
 
@@ -1732,7 +1732,7 @@  discard block
 block discarded – undo
1732 1732
         // loop through the array and setup content
1733 1733
         foreach ($help_array as $trigger => $help) {
1734 1734
             // make sure the array is setup properly
1735
-            if (! isset($help['title'], $help['content'])) {
1735
+            if ( ! isset($help['title'], $help['content'])) {
1736 1736
                 throw new EE_Error(
1737 1737
                     esc_html__(
1738 1738
                         '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',
@@ -1746,8 +1746,8 @@  discard block
 block discarded – undo
1746 1746
                 'help_popup_title'   => $help['title'],
1747 1747
                 'help_popup_content' => $help['content'],
1748 1748
             ];
1749
-            $content       .= EEH_Template::display_template(
1750
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1749
+            $content .= EEH_Template::display_template(
1750
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1751 1751
                 $template_args,
1752 1752
                 true
1753 1753
             );
@@ -1769,15 +1769,15 @@  discard block
 block discarded – undo
1769 1769
     private function _get_help_content()
1770 1770
     {
1771 1771
         // what is the method we're looking for?
1772
-        $method_name = '_help_popup_content_' . $this->_req_action;
1772
+        $method_name = '_help_popup_content_'.$this->_req_action;
1773 1773
         // if method doesn't exist let's get out.
1774
-        if (! method_exists($this, $method_name)) {
1774
+        if ( ! method_exists($this, $method_name)) {
1775 1775
             return [];
1776 1776
         }
1777 1777
         // k we're good to go let's retrieve the help array
1778 1778
         $help_array = $this->{$method_name}();
1779 1779
         // make sure we've got an array!
1780
-        if (! is_array($help_array)) {
1780
+        if ( ! is_array($help_array)) {
1781 1781
             throw new EE_Error(
1782 1782
                 esc_html__(
1783 1783
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1809,8 +1809,8 @@  discard block
 block discarded – undo
1809 1809
         // 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
1810 1810
         $help_array   = $this->_get_help_content();
1811 1811
         $help_content = '';
1812
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1813
-            $help_array[ $trigger_id ] = [
1812
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1813
+            $help_array[$trigger_id] = [
1814 1814
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1815 1815
                 'content' => esc_html__(
1816 1816
                     '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.)',
@@ -1905,7 +1905,7 @@  discard block
 block discarded – undo
1905 1905
 
1906 1906
         add_filter(
1907 1907
             'admin_body_class',
1908
-            function ($classes) {
1908
+            function($classes) {
1909 1909
                 if (strpos($classes, 'espresso-admin') === false) {
1910 1910
                     $classes .= ' espresso-admin';
1911 1911
                 }
@@ -1996,12 +1996,12 @@  discard block
 block discarded – undo
1996 1996
     protected function _set_list_table()
1997 1997
     {
1998 1998
         // first is this a list_table view?
1999
-        if (! isset($this->_route_config['list_table'])) {
1999
+        if ( ! isset($this->_route_config['list_table'])) {
2000 2000
             return;
2001 2001
         } //not a list_table view so get out.
2002 2002
         // list table functions are per view specific (because some admin pages might have more than one list table!)
2003
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2004
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2003
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
2004
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2005 2005
             // user error msg
2006 2006
             $error_msg = esc_html__(
2007 2007
                 'An error occurred. The requested list table views could not be found.',
@@ -2021,10 +2021,10 @@  discard block
 block discarded – undo
2021 2021
         }
2022 2022
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2023 2023
         $this->_views = apply_filters(
2024
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2024
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2025 2025
             $this->_views
2026 2026
         );
2027
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2027
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2028 2028
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2029 2029
         $this->_set_list_table_view();
2030 2030
         $this->_set_list_table_object();
@@ -2059,7 +2059,7 @@  discard block
 block discarded – undo
2059 2059
     protected function _set_list_table_object()
2060 2060
     {
2061 2061
         if (isset($this->_route_config['list_table'])) {
2062
-            if (! class_exists($this->_route_config['list_table'])) {
2062
+            if ( ! class_exists($this->_route_config['list_table'])) {
2063 2063
                 throw new EE_Error(
2064 2064
                     sprintf(
2065 2065
                         esc_html__(
@@ -2097,17 +2097,17 @@  discard block
 block discarded – undo
2097 2097
         foreach ($this->_views as $key => $view) {
2098 2098
             $query_args = [];
2099 2099
             // check for current view
2100
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2100
+            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2101 2101
             $query_args['action']                        = $this->_req_action;
2102
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2102
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2103 2103
             $query_args['status']                        = $view['slug'];
2104 2104
             // merge any other arguments sent in.
2105
-            if (isset($extra_query_args[ $view['slug'] ])) {
2106
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2105
+            if (isset($extra_query_args[$view['slug']])) {
2106
+                foreach ($extra_query_args[$view['slug']] as $extra_query_arg) {
2107 2107
                     $query_args[] = $extra_query_arg;
2108 2108
                 }
2109 2109
             }
2110
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2110
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2111 2111
         }
2112 2112
         return $this->_views;
2113 2113
     }
@@ -2138,14 +2138,14 @@  discard block
 block discarded – undo
2138 2138
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2139 2139
         foreach ($values as $value) {
2140 2140
             if ($value < $max_entries) {
2141
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2141
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2142 2142
                 $entries_per_page_dropdown .= '
2143
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2143
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2144 2144
             }
2145 2145
         }
2146
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2146
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2147 2147
         $entries_per_page_dropdown .= '
2148
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2148
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2149 2149
         $entries_per_page_dropdown .= '
2150 2150
 					</select>
2151 2151
 					entries
@@ -2169,7 +2169,7 @@  discard block
 block discarded – undo
2169 2169
             empty($this->_search_btn_label) ? $this->page_label
2170 2170
                 : $this->_search_btn_label
2171 2171
         );
2172
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2172
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2173 2173
     }
2174 2174
 
2175 2175
 
@@ -2257,7 +2257,7 @@  discard block
 block discarded – undo
2257 2257
             $total_columns                                       = ! empty($screen_columns)
2258 2258
                 ? $screen_columns
2259 2259
                 : $this->_route_config['columns'][1];
2260
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2260
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2261 2261
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2262 2262
             $this->_template_args['screen']                      = $this->_current_screen;
2263 2263
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2303,7 +2303,7 @@  discard block
 block discarded – undo
2303 2303
      */
2304 2304
     protected function _espresso_ratings_request()
2305 2305
     {
2306
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2306
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2307 2307
             return;
2308 2308
         }
2309 2309
         $ratings_box_title = apply_filters(
@@ -2330,28 +2330,28 @@  discard block
 block discarded – undo
2330 2330
      */
2331 2331
     public function espresso_ratings_request()
2332 2332
     {
2333
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2333
+        EEH_Template::display_template(EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php');
2334 2334
     }
2335 2335
 
2336 2336
 
2337 2337
     public static function cached_rss_display($rss_id, $url)
2338 2338
     {
2339
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2339
+        $loading = '<p class="widget-loading hide-if-no-js">'
2340 2340
                      . esc_html__('Loading&#8230;', 'event_espresso')
2341 2341
                      . '</p><p class="hide-if-js">'
2342 2342
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2343 2343
                      . '</p>';
2344
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2345
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2346
-        $post      = '</div>' . "\n";
2347
-        $cache_key = 'ee_rss_' . md5($rss_id);
2344
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2345
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2346
+        $post      = '</div>'."\n";
2347
+        $cache_key = 'ee_rss_'.md5($rss_id);
2348 2348
         $output    = get_transient($cache_key);
2349 2349
         if ($output !== false) {
2350
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2350
+            echo wp_kses($pre.$output.$post, AllowedTags::getWithFormTags());
2351 2351
             return true;
2352 2352
         }
2353
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2353
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2354
+            echo wp_kses($pre.$loading.$post, AllowedTags::getWithFormTags());
2355 2355
             return false;
2356 2356
         }
2357 2357
         ob_start();
@@ -2418,19 +2418,19 @@  discard block
 block discarded – undo
2418 2418
     public function espresso_sponsors_post_box()
2419 2419
     {
2420 2420
         EEH_Template::display_template(
2421
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2421
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2422 2422
         );
2423 2423
     }
2424 2424
 
2425 2425
 
2426 2426
     private function _publish_post_box()
2427 2427
     {
2428
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2428
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2429 2429
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2430 2430
         // then we'll use that for the metabox label.
2431 2431
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2432
-        if (! empty($this->_labels['publishbox'])) {
2433
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2432
+        if ( ! empty($this->_labels['publishbox'])) {
2433
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2434 2434
                 : $this->_labels['publishbox'];
2435 2435
         } else {
2436 2436
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2459,7 +2459,7 @@  discard block
 block discarded – undo
2459 2459
             ? $this->_template_args['publish_box_extra_content']
2460 2460
             : '';
2461 2461
         echo EEH_Template::display_template(
2462
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2462
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2463 2463
             $this->_template_args,
2464 2464
             true
2465 2465
         );
@@ -2547,18 +2547,18 @@  discard block
 block discarded – undo
2547 2547
             );
2548 2548
         }
2549 2549
         $this->_template_args['publish_delete_link'] = $delete_link;
2550
-        if (! empty($name) && ! empty($id)) {
2551
-            $hidden_field_arr[ $name ] = [
2550
+        if ( ! empty($name) && ! empty($id)) {
2551
+            $hidden_field_arr[$name] = [
2552 2552
                 'type'  => 'hidden',
2553 2553
                 'value' => $id,
2554 2554
             ];
2555
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2555
+            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2556 2556
         } else {
2557 2557
             $hf = '';
2558 2558
         }
2559 2559
         // add hidden field
2560 2560
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2561
-            ? $hf[ $name ]['field']
2561
+            ? $hf[$name]['field']
2562 2562
             : $hf;
2563 2563
     }
2564 2564
 
@@ -2660,7 +2660,7 @@  discard block
 block discarded – undo
2660 2660
         }
2661 2661
         // 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)
2662 2662
         $call_back_func = $create_func
2663
-            ? static function ($post, $metabox) {
2663
+            ? static function($post, $metabox) {
2664 2664
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2665 2665
                 echo EEH_Template::display_template(
2666 2666
                     $metabox['args']['template_path'],
@@ -2670,7 +2670,7 @@  discard block
 block discarded – undo
2670 2670
             }
2671 2671
             : $callback;
2672 2672
         $this->addMetaBox(
2673
-            str_replace('_', '-', $action) . '-mbox',
2673
+            str_replace('_', '-', $action).'-mbox',
2674 2674
             $title,
2675 2675
             $call_back_func,
2676 2676
             $this->_wp_page_slug,
@@ -2787,13 +2787,13 @@  discard block
 block discarded – undo
2787 2787
             'event-espresso_page_espresso_',
2788 2788
             '',
2789 2789
             $this->_wp_page_slug
2790
-        ) . ' ' . $this->_req_action . '-route';
2790
+        ).' '.$this->_req_action.'-route';
2791 2791
 
2792 2792
         $template_path = $sidebar
2793 2793
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2794
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2794
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2795 2795
         if ($this->request->isAjax()) {
2796
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2796
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2797 2797
         }
2798 2798
         $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2799 2799
 
@@ -2827,11 +2827,11 @@  discard block
 block discarded – undo
2827 2827
     public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2828 2828
     {
2829 2829
         // let's generate a default preview action button if there isn't one already present.
2830
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2830
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2831 2831
             'Upgrade to Event Espresso 4 Right Now',
2832 2832
             'event_espresso'
2833 2833
         );
2834
-        $buy_now_url                                   = add_query_arg(
2834
+        $buy_now_url = add_query_arg(
2835 2835
             [
2836 2836
                 'ee_ver'       => 'ee4',
2837 2837
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2851,8 +2851,8 @@  discard block
 block discarded – undo
2851 2851
                 true
2852 2852
             )
2853 2853
             : $this->_template_args['preview_action_button'];
2854
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2855
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2854
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2855
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2856 2856
             $this->_template_args,
2857 2857
             true
2858 2858
         );
@@ -2910,7 +2910,7 @@  discard block
 block discarded – undo
2910 2910
         // setup search attributes
2911 2911
         $this->_set_search_attributes();
2912 2912
         $this->_template_args['current_page']     = $this->_wp_page_slug;
2913
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2913
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2914 2914
         $this->_template_args['table_url']        = $this->request->isAjax()
2915 2915
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2916 2916
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -2918,10 +2918,10 @@  discard block
 block discarded – undo
2918 2918
         $this->_template_args['current_route']    = $this->_req_action;
2919 2919
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2920 2920
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2921
-        if (! empty($ajax_sorting_callback)) {
2921
+        if ( ! empty($ajax_sorting_callback)) {
2922 2922
             $sortable_list_table_form_fields = wp_nonce_field(
2923
-                $ajax_sorting_callback . '_nonce',
2924
-                $ajax_sorting_callback . '_nonce',
2923
+                $ajax_sorting_callback.'_nonce',
2924
+                $ajax_sorting_callback.'_nonce',
2925 2925
                 false,
2926 2926
                 false
2927 2927
             );
@@ -2938,18 +2938,18 @@  discard block
 block discarded – undo
2938 2938
 
2939 2939
         $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2940 2940
 
2941
-        $nonce_ref          = $this->_req_action . '_nonce';
2941
+        $nonce_ref          = $this->_req_action.'_nonce';
2942 2942
         $hidden_form_fields .= '
2943
-            <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2943
+            <input type="hidden" name="' . $nonce_ref.'" value="'.wp_create_nonce($nonce_ref).'">';
2944 2944
 
2945
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
2945
+        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2946 2946
         // display message about search results?
2947 2947
         $search = $this->request->getRequestParam('s');
2948 2948
         $this->_template_args['before_list_table'] .= ! empty($search)
2949
-            ? '<p class="ee-search-results">' . sprintf(
2949
+            ? '<p class="ee-search-results">'.sprintf(
2950 2950
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2951 2951
                 trim($search, '%')
2952
-            ) . '</p>'
2952
+            ).'</p>'
2953 2953
             : '';
2954 2954
         // filter before_list_table template arg
2955 2955
         $this->_template_args['before_list_table'] = apply_filters(
@@ -2983,7 +2983,7 @@  discard block
 block discarded – undo
2983 2983
         // convert to array and filter again
2984 2984
         // arrays are easier to inject new items in a specific location,
2985 2985
         // but would not be backwards compatible, so we have to add a new filter
2986
-        $this->_template_args['after_list_table']   = implode(
2986
+        $this->_template_args['after_list_table'] = implode(
2987 2987
             " \n",
2988 2988
             (array) apply_filters(
2989 2989
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3038,7 +3038,7 @@  discard block
 block discarded – undo
3038 3038
             $this->page_slug
3039 3039
         );
3040 3040
         return EEH_Template::display_template(
3041
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3041
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3042 3042
             $this->_template_args,
3043 3043
             true
3044 3044
         );
@@ -3154,16 +3154,16 @@  discard block
 block discarded – undo
3154 3154
             $this->_template_args['before_admin_page_content'] ?? ''
3155 3155
         );
3156 3156
 
3157
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3157
+        $this->_template_args['after_admin_page_content'] = apply_filters(
3158 3158
             "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3159 3159
             $this->_template_args['after_admin_page_content'] ?? ''
3160 3160
         );
3161
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3161
+        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3162 3162
 
3163 3163
         if ($this->request->isAjax()) {
3164 3164
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3165 3165
                 // $template_path,
3166
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3166
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3167 3167
                 $this->_template_args,
3168 3168
                 true
3169 3169
             );
@@ -3172,7 +3172,7 @@  discard block
 block discarded – undo
3172 3172
         // load settings page wrapper template
3173 3173
         $template_path = $about
3174 3174
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3175
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3175
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3176 3176
 
3177 3177
         EEH_Template::display_template($template_path, $this->_template_args);
3178 3178
     }
@@ -3256,12 +3256,12 @@  discard block
 block discarded – undo
3256 3256
         $default_names = ['save', 'save_and_close'];
3257 3257
         $buttons = '';
3258 3258
         foreach ($button_text as $key => $button) {
3259
-            $ref     = $default_names[ $key ];
3260
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3261
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3262
-                        . 'value="' . $button . '" name="' . $name . '" '
3263
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3264
-            if (! $both) {
3259
+            $ref     = $default_names[$key];
3260
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3261
+            $buttons .= '<input type="submit" class="button button--primary '.$ref.'" '
3262
+                        . 'value="'.$button.'" name="'.$name.'" '
3263
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3264
+            if ( ! $both) {
3265 3265
                 break;
3266 3266
             }
3267 3267
         }
@@ -3301,13 +3301,13 @@  discard block
 block discarded – undo
3301 3301
                 'An error occurred. No action was set for this page\'s form.',
3302 3302
                 'event_espresso'
3303 3303
             );
3304
-            $dev_msg  = $user_msg . "\n"
3304
+            $dev_msg = $user_msg."\n"
3305 3305
                         . sprintf(
3306 3306
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3307 3307
                             __FUNCTION__,
3308 3308
                             __CLASS__
3309 3309
                         );
3310
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3310
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3311 3311
         }
3312 3312
         // open form
3313 3313
         $action = $this->_admin_base_url;
@@ -3315,9 +3315,9 @@  discard block
 block discarded – undo
3315 3315
             <form name='form' method='post' action='{$action}' id='{$route}_event_form' class='ee-admin-page-form' >
3316 3316
             ";
3317 3317
         // add nonce
3318
-        $nonce                                             =
3319
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3320
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3318
+        $nonce =
3319
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3320
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3321 3321
         // add REQUIRED form action
3322 3322
         $hidden_fields = [
3323 3323
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3330,7 +3330,7 @@  discard block
 block discarded – undo
3330 3330
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3331 3331
         // add fields to form
3332 3332
         foreach ((array) $form_fields as $form_field) {
3333
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3333
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3334 3334
         }
3335 3335
         // close form
3336 3336
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3413,12 +3413,12 @@  discard block
 block discarded – undo
3413 3413
         bool $override_overwrite = false
3414 3414
     ) {
3415 3415
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3416
-        $notices      = EE_Error::get_notices(false);
3416
+        $notices = EE_Error::get_notices(false);
3417 3417
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3418
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3418
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3419 3419
             EE_Error::overwrite_success();
3420 3420
         }
3421
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3421
+        if ( ! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3422 3422
             // how many records affected ? more than one record ? or just one ?
3423 3423
             EE_Error::add_success(
3424 3424
                 sprintf(
@@ -3439,7 +3439,7 @@  discard block
 block discarded – undo
3439 3439
             );
3440 3440
         }
3441 3441
         // check that $query_args isn't something crazy
3442
-        if (! is_array($query_args)) {
3442
+        if ( ! is_array($query_args)) {
3443 3443
             $query_args = [];
3444 3444
         }
3445 3445
         /**
@@ -3471,7 +3471,7 @@  discard block
 block discarded – undo
3471 3471
             $redirect_url = admin_url('admin.php');
3472 3472
         }
3473 3473
         // merge any default query_args set in _default_route_query_args property
3474
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3474
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3475 3475
             $args_to_merge = [];
3476 3476
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3477 3477
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3483,15 +3483,15 @@  discard block
 block discarded – undo
3483 3483
                         }
3484 3484
                         // finally we will override any arguments in the referer with
3485 3485
                         // what might be set on the _default_route_query_args array.
3486
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3487
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3486
+                        if (isset($this->_default_route_query_args[$reference])) {
3487
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3488 3488
                         } else {
3489
-                            $args_to_merge[ $reference ] = urlencode($value);
3489
+                            $args_to_merge[$reference] = urlencode($value);
3490 3490
                         }
3491 3491
                     }
3492 3492
                     continue;
3493 3493
                 }
3494
-                $args_to_merge[ $query_param ] = $query_value;
3494
+                $args_to_merge[$query_param] = $query_value;
3495 3495
             }
3496 3496
             // now let's merge these arguments but override with what was specifically sent in to the
3497 3497
             // redirect.
@@ -3503,19 +3503,19 @@  discard block
 block discarded – undo
3503 3503
         if (isset($query_args['action'])) {
3504 3504
             // manually generate wp_nonce and merge that with the query vars
3505 3505
             // becuz the wp_nonce_url function wrecks havoc on some vars
3506
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3506
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3507 3507
         }
3508 3508
         // we're adding some hooks and filters in here for processing any things just before redirects
3509 3509
         // (example: an admin page has done an insert or update and we want to run something after that).
3510
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3510
+        do_action('AHEE_redirect_'.$this->class_name.$this->_req_action, $query_args);
3511 3511
         $redirect_url = apply_filters(
3512
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3512
+            'FHEE_redirect_'.$this->class_name.$this->_req_action,
3513 3513
             EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3514 3514
             $query_args
3515 3515
         );
3516 3516
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3517 3517
         if ($this->request->isAjax()) {
3518
-            $default_data                    = [
3518
+            $default_data = [
3519 3519
                 'close'        => true,
3520 3520
                 'redirect_url' => $redirect_url,
3521 3521
                 'where'        => 'main',
@@ -3565,7 +3565,7 @@  discard block
 block discarded – undo
3565 3565
         }
3566 3566
         $this->_template_args['notices'] = EE_Error::get_notices();
3567 3567
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3568
-        if (! $this->request->isAjax() || $sticky_notices) {
3568
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3569 3569
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3570 3570
             $this->_add_transient(
3571 3571
                 $route,
@@ -3605,7 +3605,7 @@  discard block
 block discarded – undo
3605 3605
         $exclude_nonce = false
3606 3606
     ) {
3607 3607
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3608
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3608
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3609 3609
             throw new EE_Error(
3610 3610
                 sprintf(
3611 3611
                     esc_html__(
@@ -3616,7 +3616,7 @@  discard block
 block discarded – undo
3616 3616
                 )
3617 3617
             );
3618 3618
         }
3619
-        if (! isset($this->_labels['buttons'][ $type ])) {
3619
+        if ( ! isset($this->_labels['buttons'][$type])) {
3620 3620
             throw new EE_Error(
3621 3621
                 sprintf(
3622 3622
                     esc_html__(
@@ -3629,7 +3629,7 @@  discard block
 block discarded – undo
3629 3629
         }
3630 3630
         // finally check user access for this button.
3631 3631
         $has_access = $this->check_user_access($action, true);
3632
-        if (! $has_access) {
3632
+        if ( ! $has_access) {
3633 3633
             return '';
3634 3634
         }
3635 3635
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3637,11 +3637,11 @@  discard block
 block discarded – undo
3637 3637
             'action' => $action,
3638 3638
         ];
3639 3639
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3640
-        if (! empty($extra_request)) {
3640
+        if ( ! empty($extra_request)) {
3641 3641
             $query_args = array_merge($extra_request, $query_args);
3642 3642
         }
3643 3643
         $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3644
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3644
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3645 3645
     }
3646 3646
 
3647 3647
 
@@ -3667,7 +3667,7 @@  discard block
 block discarded – undo
3667 3667
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3668 3668
                 20
3669 3669
             ),
3670
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3670
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3671 3671
         ];
3672 3672
         // ONLY add the screen option if the user has access to it.
3673 3673
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3688,18 +3688,18 @@  discard block
 block discarded – undo
3688 3688
     {
3689 3689
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3690 3690
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3691
-            if (! $user = wp_get_current_user()) {
3691
+            if ( ! $user = wp_get_current_user()) {
3692 3692
                 return;
3693 3693
             }
3694 3694
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3695
-            if (! $option) {
3695
+            if ( ! $option) {
3696 3696
                 return;
3697 3697
             }
3698
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3698
+            $value = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3699 3699
             $map_option = $option;
3700 3700
             $option     = str_replace('-', '_', $option);
3701 3701
             switch ($map_option) {
3702
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3702
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3703 3703
                     $max_value = apply_filters(
3704 3704
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3705 3705
                         999,
@@ -3756,13 +3756,13 @@  discard block
 block discarded – undo
3756 3756
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3757 3757
     {
3758 3758
         $user_id = get_current_user_id();
3759
-        if (! $skip_route_verify) {
3759
+        if ( ! $skip_route_verify) {
3760 3760
             $this->_verify_route($route);
3761 3761
         }
3762 3762
         // now let's set the string for what kind of transient we're setting
3763 3763
         $transient = $notices
3764
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3765
-            : 'rte_tx_' . $route . '_' . $user_id;
3764
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3765
+            : 'rte_tx_'.$route.'_'.$user_id;
3766 3766
         $data      = $notices ? ['notices' => $data] : $data;
3767 3767
         // is there already a transient for this route?  If there is then let's ADD to that transient
3768 3768
         $existing = is_multisite() && is_network_admin()
@@ -3791,8 +3791,8 @@  discard block
 block discarded – undo
3791 3791
         $user_id   = get_current_user_id();
3792 3792
         $route     = ! $route ? $this->_req_action : $route;
3793 3793
         $transient = $notices
3794
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3795
-            : 'rte_tx_' . $route . '_' . $user_id;
3794
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3795
+            : 'rte_tx_'.$route.'_'.$user_id;
3796 3796
         $data      = is_multisite() && is_network_admin()
3797 3797
             ? get_site_transient($transient)
3798 3798
             : get_transient($transient);
@@ -4028,7 +4028,7 @@  discard block
 block discarded – undo
4028 4028
      */
4029 4029
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4030 4030
     {
4031
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4031
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4032 4032
     }
4033 4033
 
4034 4034
 
@@ -4041,7 +4041,7 @@  discard block
 block discarded – undo
4041 4041
      */
4042 4042
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4043 4043
     {
4044
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4044
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4045 4045
     }
4046 4046
 
4047 4047
 
@@ -4189,7 +4189,7 @@  discard block
 block discarded – undo
4189 4189
         ?callable $callback = null
4190 4190
     ): bool {
4191 4191
         $entity_ID = absint($entity_ID);
4192
-        if (! $entity_ID) {
4192
+        if ( ! $entity_ID) {
4193 4193
             $this->trashRestoreDeleteError($action, $entity_model);
4194 4194
         }
4195 4195
         $result = 0;
@@ -4235,7 +4235,7 @@  discard block
 block discarded – undo
4235 4235
                 )
4236 4236
             );
4237 4237
         }
4238
-        if (! $entity_model->has_field($delete_column)) {
4238
+        if ( ! $entity_model->has_field($delete_column)) {
4239 4239
             throw new DomainException(
4240 4240
                 sprintf(
4241 4241
                     esc_html__(
Please login to merge, or discard this patch.
core/EE_Addon.core.php 2 patches
Indentation   +859 added lines, -859 removed lines patch added patch discarded remove patch
@@ -17,870 +17,870 @@
 block discarded – undo
17 17
  */
18 18
 abstract class EE_Addon extends EE_Configurable implements RequiresDependencyMapInterface, RequiresDomainInterface
19 19
 {
20
-    /**
21
-     * prefix to be added onto an addon's plugin slug to make a wp option name
22
-     * which will be used to store the plugin's activation history
23
-     */
24
-    const ee_addon_version_history_option_prefix = 'ee_version_history_';
25
-
26
-    /**
27
-     * @var $_version
28
-     * @type string
29
-     */
30
-    protected $_version = '';
31
-
32
-    /**
33
-     * @var $_min_core_version
34
-     * @type string
35
-     */
36
-    protected $_min_core_version = '';
37
-
38
-    /**
39
-     * derived from plugin 'main_file_path using plugin_basename()
40
-     *
41
-     * @type string $_plugin_basename
42
-     */
43
-    protected $_plugin_basename = '';
44
-
45
-    /**
46
-     * A non-internationalized name to identify this addon for use in URLs, etc
47
-     *
48
-     * @type string $_plugin_slug
49
-     */
50
-    protected $_plugin_slug = '';
51
-
52
-    /**
53
-     * A non-internationalized name to identify this addon. Eg 'Calendar','MailChimp',etc/
54
-     *
55
-     * @type string _addon_name
56
-     */
57
-    protected $_addon_name = '';
58
-
59
-    /**
60
-     * one of the EE_System::req_type_* constants
61
-     *
62
-     * @type int $_req_type
63
-     */
64
-    protected $_req_type;
65
-
66
-    /**
67
-     * page slug to be used when generating the "Settings" link on the WP plugin page
68
-     *
69
-     * @type string $_plugin_action_slug
70
-     */
71
-    protected $_plugin_action_slug = '';
72
-
73
-    /**
74
-     * if not empty, inserts a new table row after this plugin's row on the WP Plugins page
75
-     * that can be used for adding upgrading/marketing info
76
-     *
77
-     * @type array $_plugins_page_row
78
-     */
79
-    protected $_plugins_page_row = [];
80
-
81
-
82
-    /**
83
-     *    filepath to the main file, which can be used for register_activation_hook, register_deactivation_hook, etc.
84
-     *
85
-     * @type string
86
-     */
87
-    protected $_main_plugin_file;
88
-
89
-    /**
90
-     *    This is the slug used to identify this add-on within the plugin update engine.
91
-     *
92
-     * @type string
93
-     */
94
-    protected $pue_slug = '';
95
-
96
-
97
-    /**
98
-     * @var EE_Dependency_Map $dependency_map
99
-     */
100
-    private $dependency_map;
101
-
102
-
103
-    /**
104
-     * @var DomainInterface $domain
105
-     */
106
-    private $domain;
107
-
108
-
109
-    /**
110
-     * @param EE_Dependency_Map|null $dependency_map [optional]
111
-     * @param DomainInterface|null   $domain         [optional]
112
-     */
113
-    public function __construct(EE_Dependency_Map $dependency_map = null, DomainInterface $domain = null)
114
-    {
115
-        if ($dependency_map instanceof EE_Dependency_Map) {
116
-            $this->setDependencyMap($dependency_map);
117
-        }
118
-        if ($domain instanceof DomainInterface) {
119
-            $this->setDomain($domain);
120
-        }
121
-        add_action('AHEE__EE_System__load_controllers__load_admin_controllers', [$this, 'admin_init']);
122
-    }
123
-
124
-
125
-    /**
126
-     * @param EE_Dependency_Map $dependency_map
127
-     */
128
-    public function setDependencyMap($dependency_map)
129
-    {
130
-        $this->dependency_map = $dependency_map;
131
-    }
132
-
133
-
134
-    /**
135
-     * @return EE_Dependency_Map
136
-     */
137
-    public function dependencyMap(): ?EE_Dependency_Map
138
-    {
139
-        return $this->dependency_map;
140
-    }
141
-
142
-
143
-    /**
144
-     * @param DomainInterface $domain
145
-     */
146
-    public function setDomain(DomainInterface $domain)
147
-    {
148
-        $this->domain = $domain;
149
-    }
150
-
151
-
152
-    /**
153
-     * @return DomainInterface
154
-     */
155
-    public function domain(): ?DomainInterface
156
-    {
157
-        return $this->domain;
158
-    }
159
-
160
-
161
-    /**
162
-     * @param string $version
163
-     */
164
-    public function set_version(string $version = '')
165
-    {
166
-        $this->_version = $version;
167
-    }
168
-
169
-
170
-    /**
171
-     * get__version
172
-     *
173
-     * @return string
174
-     */
175
-    public function version(): string
176
-    {
177
-        return $this->_version;
178
-    }
179
-
180
-
181
-    /**
182
-     * @param mixed $min_core_version
183
-     */
184
-    public function set_min_core_version($min_core_version = null)
185
-    {
186
-        $this->_min_core_version = $min_core_version;
187
-    }
188
-
189
-
190
-    /**
191
-     * get__min_core_version
192
-     *
193
-     * @return string
194
-     */
195
-    public function min_core_version(): string
196
-    {
197
-        return $this->_min_core_version;
198
-    }
199
-
200
-
201
-    /**
202
-     * Sets addon_name
203
-     *
204
-     * @param string $addon_name
205
-     */
206
-    public function set_name(string $addon_name)
207
-    {
208
-        $this->_addon_name = $addon_name;
209
-    }
210
-
211
-
212
-    /**
213
-     * Gets addon_name
214
-     *
215
-     * @return string
216
-     */
217
-    public function name()
218
-    {
219
-        return $this->_addon_name;
220
-    }
221
-
222
-
223
-    /**
224
-     * @return string
225
-     */
226
-    public function plugin_basename(): string
227
-    {
228
-
229
-        return $this->_plugin_basename;
230
-    }
231
-
232
-
233
-    /**
234
-     * @param string $plugin_basename
235
-     */
236
-    public function set_plugin_basename(string $plugin_basename)
237
-    {
238
-
239
-        $this->_plugin_basename = $plugin_basename;
240
-    }
241
-
242
-
243
-    /**
244
-     * @return string
245
-     */
246
-    public function plugin_slug(): string
247
-    {
248
-
249
-        return $this->_plugin_slug;
250
-    }
251
-
252
-
253
-    /**
254
-     * @param string $plugin_slug
255
-     */
256
-    public function set_plugin_slug(string $plugin_slug)
257
-    {
258
-
259
-        $this->_plugin_slug = $plugin_slug;
260
-    }
261
-
262
-
263
-    /**
264
-     * @return string
265
-     */
266
-    public function plugin_action_slug(): string
267
-    {
268
-
269
-        return $this->_plugin_action_slug;
270
-    }
271
-
272
-
273
-    /**
274
-     * @param string $plugin_action_slug
275
-     */
276
-    public function set_plugin_action_slug(string $plugin_action_slug)
277
-    {
278
-
279
-        $this->_plugin_action_slug = $plugin_action_slug;
280
-    }
281
-
282
-
283
-    /**
284
-     * @return array
285
-     */
286
-    public function get_plugins_page_row(): array
287
-    {
288
-
289
-        return $this->_plugins_page_row;
290
-    }
291
-
292
-
293
-    /**
294
-     * @param array|string $plugins_page_row
295
-     */
296
-    public function set_plugins_page_row(array $plugins_page_row = [])
297
-    {
298
-        // sigh.... check for example content that I stupidly merged to master and remove it if found
299
-        if (
300
-            ! is_array($plugins_page_row)
301
-            && strpos($plugins_page_row, '<h3>Promotions Addon Upsell Info</h3>') !== false
302
-        ) {
303
-            $plugins_page_row = [];
304
-        }
305
-        $this->_plugins_page_row = (array) $plugins_page_row;
306
-    }
307
-
308
-
309
-    /**
310
-     * Called when EE core detects this addon has been activated for the first time.
311
-     * If the site isn't in maintenance mode, should setup the addon's database
312
-     *
313
-     * @return void
314
-     * @throws EE_Error
315
-     */
316
-    public function new_install()
317
-    {
318
-        $classname = get_class($this);
319
-        do_action("AHEE__{$classname}__new_install");
320
-        do_action('AHEE__EE_Addon__new_install', $this);
321
-        EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
322
-        add_action(
323
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
324
-            [$this, 'initialize_db_if_no_migrations_required']
325
-        );
326
-    }
327
-
328
-
329
-    /**
330
-     * Called when EE core detects this addon has been reactivated. When this happens,
331
-     * it's good to just check that your data is still intact
332
-     *
333
-     * @return void
334
-     * @throws EE_Error
335
-     */
336
-    public function reactivation()
337
-    {
338
-        $classname = get_class($this);
339
-        do_action("AHEE__{$classname}__reactivation");
340
-        do_action('AHEE__EE_Addon__reactivation', $this);
341
-        EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
342
-        add_action(
343
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
344
-            [$this, 'initialize_db_if_no_migrations_required']
345
-        );
346
-    }
347
-
348
-
349
-    /**
350
-     * Called when the registered deactivation hook for this addon fires.
351
-     *
352
-     * @throws EE_Error
353
-     */
354
-    public function deactivation()
355
-    {
356
-        $classname = get_class($this);
357
-        do_action("AHEE__{$classname}__deactivation");
358
-        do_action('AHEE__EE_Addon__deactivation', $this);
359
-        // check if the site no longer needs to be in maintenance mode
360
-        EE_Register_Addon::deregister($this->name());
361
-        EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
362
-    }
363
-
364
-
365
-    /**
366
-     * Takes care of double-checking that we're not in maintenance mode, and then
367
-     * initializing this addon's necessary initial data. This is called by default on new activations
368
-     * and reactivations.
369
-     *
370
-     * @param bool $verify_schema whether to verify the database's schema for this addon, or just its data.
371
-     *                               This is a resource-intensive job so we prefer to only do it when necessary
372
-     * @return void
373
-     * @throws EE_Error
374
-     * @throws InvalidInterfaceException
375
-     * @throws InvalidDataTypeException
376
-     * @throws InvalidArgumentException
377
-     * @throws ReflectionException
378
-     */
379
-    public function initialize_db_if_no_migrations_required($verify_schema = true)
380
-    {
381
-        if ($verify_schema === '') {
382
-            // wp core bug imo: if no args are passed to `do_action('some_hook_name')` besides the hook's name
383
-            // (ie, no 2nd or 3rd arguments), instead of calling the registered callbacks with no arguments, it
384
-            // calls them with an argument of an empty string (ie ""), which evaluates to false
385
-            // so we need to treat the empty string as if nothing had been passed, and should instead use the default
386
-            $verify_schema = true;
387
-        }
388
-        if (EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
389
-            if ($verify_schema) {
390
-                $this->initialize_db();
391
-            }
392
-            $this->initialize_default_data();
393
-            // @todo: this will probably need to be adjusted in 4.4 as the array changed formats I believe
394
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to(
395
-                [
396
-                    'slug'    => $this->name(),
397
-                    'version' => $this->version(),
398
-                ]
399
-            );
400
-            /* make sure core's data is a-ok
20
+	/**
21
+	 * prefix to be added onto an addon's plugin slug to make a wp option name
22
+	 * which will be used to store the plugin's activation history
23
+	 */
24
+	const ee_addon_version_history_option_prefix = 'ee_version_history_';
25
+
26
+	/**
27
+	 * @var $_version
28
+	 * @type string
29
+	 */
30
+	protected $_version = '';
31
+
32
+	/**
33
+	 * @var $_min_core_version
34
+	 * @type string
35
+	 */
36
+	protected $_min_core_version = '';
37
+
38
+	/**
39
+	 * derived from plugin 'main_file_path using plugin_basename()
40
+	 *
41
+	 * @type string $_plugin_basename
42
+	 */
43
+	protected $_plugin_basename = '';
44
+
45
+	/**
46
+	 * A non-internationalized name to identify this addon for use in URLs, etc
47
+	 *
48
+	 * @type string $_plugin_slug
49
+	 */
50
+	protected $_plugin_slug = '';
51
+
52
+	/**
53
+	 * A non-internationalized name to identify this addon. Eg 'Calendar','MailChimp',etc/
54
+	 *
55
+	 * @type string _addon_name
56
+	 */
57
+	protected $_addon_name = '';
58
+
59
+	/**
60
+	 * one of the EE_System::req_type_* constants
61
+	 *
62
+	 * @type int $_req_type
63
+	 */
64
+	protected $_req_type;
65
+
66
+	/**
67
+	 * page slug to be used when generating the "Settings" link on the WP plugin page
68
+	 *
69
+	 * @type string $_plugin_action_slug
70
+	 */
71
+	protected $_plugin_action_slug = '';
72
+
73
+	/**
74
+	 * if not empty, inserts a new table row after this plugin's row on the WP Plugins page
75
+	 * that can be used for adding upgrading/marketing info
76
+	 *
77
+	 * @type array $_plugins_page_row
78
+	 */
79
+	protected $_plugins_page_row = [];
80
+
81
+
82
+	/**
83
+	 *    filepath to the main file, which can be used for register_activation_hook, register_deactivation_hook, etc.
84
+	 *
85
+	 * @type string
86
+	 */
87
+	protected $_main_plugin_file;
88
+
89
+	/**
90
+	 *    This is the slug used to identify this add-on within the plugin update engine.
91
+	 *
92
+	 * @type string
93
+	 */
94
+	protected $pue_slug = '';
95
+
96
+
97
+	/**
98
+	 * @var EE_Dependency_Map $dependency_map
99
+	 */
100
+	private $dependency_map;
101
+
102
+
103
+	/**
104
+	 * @var DomainInterface $domain
105
+	 */
106
+	private $domain;
107
+
108
+
109
+	/**
110
+	 * @param EE_Dependency_Map|null $dependency_map [optional]
111
+	 * @param DomainInterface|null   $domain         [optional]
112
+	 */
113
+	public function __construct(EE_Dependency_Map $dependency_map = null, DomainInterface $domain = null)
114
+	{
115
+		if ($dependency_map instanceof EE_Dependency_Map) {
116
+			$this->setDependencyMap($dependency_map);
117
+		}
118
+		if ($domain instanceof DomainInterface) {
119
+			$this->setDomain($domain);
120
+		}
121
+		add_action('AHEE__EE_System__load_controllers__load_admin_controllers', [$this, 'admin_init']);
122
+	}
123
+
124
+
125
+	/**
126
+	 * @param EE_Dependency_Map $dependency_map
127
+	 */
128
+	public function setDependencyMap($dependency_map)
129
+	{
130
+		$this->dependency_map = $dependency_map;
131
+	}
132
+
133
+
134
+	/**
135
+	 * @return EE_Dependency_Map
136
+	 */
137
+	public function dependencyMap(): ?EE_Dependency_Map
138
+	{
139
+		return $this->dependency_map;
140
+	}
141
+
142
+
143
+	/**
144
+	 * @param DomainInterface $domain
145
+	 */
146
+	public function setDomain(DomainInterface $domain)
147
+	{
148
+		$this->domain = $domain;
149
+	}
150
+
151
+
152
+	/**
153
+	 * @return DomainInterface
154
+	 */
155
+	public function domain(): ?DomainInterface
156
+	{
157
+		return $this->domain;
158
+	}
159
+
160
+
161
+	/**
162
+	 * @param string $version
163
+	 */
164
+	public function set_version(string $version = '')
165
+	{
166
+		$this->_version = $version;
167
+	}
168
+
169
+
170
+	/**
171
+	 * get__version
172
+	 *
173
+	 * @return string
174
+	 */
175
+	public function version(): string
176
+	{
177
+		return $this->_version;
178
+	}
179
+
180
+
181
+	/**
182
+	 * @param mixed $min_core_version
183
+	 */
184
+	public function set_min_core_version($min_core_version = null)
185
+	{
186
+		$this->_min_core_version = $min_core_version;
187
+	}
188
+
189
+
190
+	/**
191
+	 * get__min_core_version
192
+	 *
193
+	 * @return string
194
+	 */
195
+	public function min_core_version(): string
196
+	{
197
+		return $this->_min_core_version;
198
+	}
199
+
200
+
201
+	/**
202
+	 * Sets addon_name
203
+	 *
204
+	 * @param string $addon_name
205
+	 */
206
+	public function set_name(string $addon_name)
207
+	{
208
+		$this->_addon_name = $addon_name;
209
+	}
210
+
211
+
212
+	/**
213
+	 * Gets addon_name
214
+	 *
215
+	 * @return string
216
+	 */
217
+	public function name()
218
+	{
219
+		return $this->_addon_name;
220
+	}
221
+
222
+
223
+	/**
224
+	 * @return string
225
+	 */
226
+	public function plugin_basename(): string
227
+	{
228
+
229
+		return $this->_plugin_basename;
230
+	}
231
+
232
+
233
+	/**
234
+	 * @param string $plugin_basename
235
+	 */
236
+	public function set_plugin_basename(string $plugin_basename)
237
+	{
238
+
239
+		$this->_plugin_basename = $plugin_basename;
240
+	}
241
+
242
+
243
+	/**
244
+	 * @return string
245
+	 */
246
+	public function plugin_slug(): string
247
+	{
248
+
249
+		return $this->_plugin_slug;
250
+	}
251
+
252
+
253
+	/**
254
+	 * @param string $plugin_slug
255
+	 */
256
+	public function set_plugin_slug(string $plugin_slug)
257
+	{
258
+
259
+		$this->_plugin_slug = $plugin_slug;
260
+	}
261
+
262
+
263
+	/**
264
+	 * @return string
265
+	 */
266
+	public function plugin_action_slug(): string
267
+	{
268
+
269
+		return $this->_plugin_action_slug;
270
+	}
271
+
272
+
273
+	/**
274
+	 * @param string $plugin_action_slug
275
+	 */
276
+	public function set_plugin_action_slug(string $plugin_action_slug)
277
+	{
278
+
279
+		$this->_plugin_action_slug = $plugin_action_slug;
280
+	}
281
+
282
+
283
+	/**
284
+	 * @return array
285
+	 */
286
+	public function get_plugins_page_row(): array
287
+	{
288
+
289
+		return $this->_plugins_page_row;
290
+	}
291
+
292
+
293
+	/**
294
+	 * @param array|string $plugins_page_row
295
+	 */
296
+	public function set_plugins_page_row(array $plugins_page_row = [])
297
+	{
298
+		// sigh.... check for example content that I stupidly merged to master and remove it if found
299
+		if (
300
+			! is_array($plugins_page_row)
301
+			&& strpos($plugins_page_row, '<h3>Promotions Addon Upsell Info</h3>') !== false
302
+		) {
303
+			$plugins_page_row = [];
304
+		}
305
+		$this->_plugins_page_row = (array) $plugins_page_row;
306
+	}
307
+
308
+
309
+	/**
310
+	 * Called when EE core detects this addon has been activated for the first time.
311
+	 * If the site isn't in maintenance mode, should setup the addon's database
312
+	 *
313
+	 * @return void
314
+	 * @throws EE_Error
315
+	 */
316
+	public function new_install()
317
+	{
318
+		$classname = get_class($this);
319
+		do_action("AHEE__{$classname}__new_install");
320
+		do_action('AHEE__EE_Addon__new_install', $this);
321
+		EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
322
+		add_action(
323
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
324
+			[$this, 'initialize_db_if_no_migrations_required']
325
+		);
326
+	}
327
+
328
+
329
+	/**
330
+	 * Called when EE core detects this addon has been reactivated. When this happens,
331
+	 * it's good to just check that your data is still intact
332
+	 *
333
+	 * @return void
334
+	 * @throws EE_Error
335
+	 */
336
+	public function reactivation()
337
+	{
338
+		$classname = get_class($this);
339
+		do_action("AHEE__{$classname}__reactivation");
340
+		do_action('AHEE__EE_Addon__reactivation', $this);
341
+		EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
342
+		add_action(
343
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
344
+			[$this, 'initialize_db_if_no_migrations_required']
345
+		);
346
+	}
347
+
348
+
349
+	/**
350
+	 * Called when the registered deactivation hook for this addon fires.
351
+	 *
352
+	 * @throws EE_Error
353
+	 */
354
+	public function deactivation()
355
+	{
356
+		$classname = get_class($this);
357
+		do_action("AHEE__{$classname}__deactivation");
358
+		do_action('AHEE__EE_Addon__deactivation', $this);
359
+		// check if the site no longer needs to be in maintenance mode
360
+		EE_Register_Addon::deregister($this->name());
361
+		EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
362
+	}
363
+
364
+
365
+	/**
366
+	 * Takes care of double-checking that we're not in maintenance mode, and then
367
+	 * initializing this addon's necessary initial data. This is called by default on new activations
368
+	 * and reactivations.
369
+	 *
370
+	 * @param bool $verify_schema whether to verify the database's schema for this addon, or just its data.
371
+	 *                               This is a resource-intensive job so we prefer to only do it when necessary
372
+	 * @return void
373
+	 * @throws EE_Error
374
+	 * @throws InvalidInterfaceException
375
+	 * @throws InvalidDataTypeException
376
+	 * @throws InvalidArgumentException
377
+	 * @throws ReflectionException
378
+	 */
379
+	public function initialize_db_if_no_migrations_required($verify_schema = true)
380
+	{
381
+		if ($verify_schema === '') {
382
+			// wp core bug imo: if no args are passed to `do_action('some_hook_name')` besides the hook's name
383
+			// (ie, no 2nd or 3rd arguments), instead of calling the registered callbacks with no arguments, it
384
+			// calls them with an argument of an empty string (ie ""), which evaluates to false
385
+			// so we need to treat the empty string as if nothing had been passed, and should instead use the default
386
+			$verify_schema = true;
387
+		}
388
+		if (EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
389
+			if ($verify_schema) {
390
+				$this->initialize_db();
391
+			}
392
+			$this->initialize_default_data();
393
+			// @todo: this will probably need to be adjusted in 4.4 as the array changed formats I believe
394
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to(
395
+				[
396
+					'slug'    => $this->name(),
397
+					'version' => $this->version(),
398
+				]
399
+			);
400
+			/* make sure core's data is a-ok
401 401
              * (at the time of writing, we especially want to verify all the caps are present
402 402
              * because payment method type capabilities are added dynamically, and it's
403 403
              * possible this addon added a payment method. But it's also possible
404 404
              * other data needs to be verified)
405 405
              */
406
-            EEH_Activation::initialize_db_content();
407
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
408
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
409
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
410
-            );
411
-            $rewrite_rules->flushRewriteRules();
412
-            // in case there are lots of addons being activated at once, let's force garbage collection
413
-            // to help avoid memory limit errors
414
-            // EEH_Debug_Tools::instance()->measure_memory( 'db content initialized for ' . get_class( $this), true );
415
-            gc_collect_cycles();
416
-        } else {
417
-            // ask the data migration manager to init this addon's data
418
-            // when migrations are finished because we can't do it now
419
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for($this->name());
420
-        }
421
-    }
422
-
423
-
424
-    /**
425
-     * Used to setup this addon's database tables, but not necessarily any default
426
-     * data in them. The default is to actually use the most up-to-date data migration script
427
-     * for this addon, and just use its schema_changes_before_migration() and schema_changes_after_migration()
428
-     * methods to setup the db.
429
-     *
430
-     * @throws EE_Error
431
-     * @throws ReflectionException
432
-     */
433
-    public function initialize_db()
434
-    {
435
-        // find the migration script that sets the database to be compatible with the code
436
-        $current_dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms($this->name());
437
-        if ($current_dms_name) {
438
-            $current_data_migration_script = EE_Registry::instance()->load_dms($current_dms_name);
439
-            $current_data_migration_script->set_migrating(false);
440
-            $current_data_migration_script->schema_changes_before_migration();
441
-            $current_data_migration_script->schema_changes_after_migration();
442
-            if ($current_data_migration_script->get_errors()) {
443
-                foreach ($current_data_migration_script->get_errors() as $error) {
444
-                    EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
445
-                }
446
-            }
447
-        }
448
-        // if not DMS was found that should be ok. This addon just doesn't require any database changes
449
-        EE_Data_Migration_Manager::instance()->update_current_database_state_to(
450
-            [
451
-                'slug'    => $this->name(),
452
-                'version' => $this->version(),
453
-            ]
454
-        );
455
-    }
456
-
457
-
458
-    /**
459
-     * If you want to setup default data for the addon, override this method, and call
460
-     * parent::initialize_default_data() from within it. This is normally called
461
-     * from EE_Addon::initialize_db_if_no_migrations_required(), just after EE_Addon::initialize_db()
462
-     * and should verify default data is present (but this is also called
463
-     * on reactivations and just after migrations, so please verify you actually want
464
-     * to ADD default data, because it may already be present).
465
-     * However, please call this parent (currently it just fires a hook which other
466
-     * addons may be depending on)
467
-     */
468
-    public function initialize_default_data()
469
-    {
470
-        /**
471
-         * Called when an addon is ensuring its default data is set (possibly called
472
-         * on a reactivation, so first check for the absence of other data before setting
473
-         * default data)
474
-         *
475
-         * @param EE_Addon $addon the addon that called this
476
-         */
477
-        do_action('AHEE__EE_Addon__initialize_default_data__begin', $this);
478
-        // override to insert default data. It is safe to use the models here
479
-        // because the site should not be in maintenance mode
480
-    }
481
-
482
-
483
-    /**
484
-     * EE Core detected that this addon has been upgraded. We should check if there
485
-     * are any new migration scripts, and if so put the site into maintenance mode until
486
-     * they're ran
487
-     *
488
-     * @return void
489
-     * @throws EE_Error
490
-     */
491
-    public function upgrade()
492
-    {
493
-        $classname = get_class($this);
494
-        do_action("AHEE__{$classname}__upgrade");
495
-        do_action('AHEE__EE_Addon__upgrade', $this);
496
-        EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
497
-        // also it's possible there is new default data that needs to be added
498
-        add_action(
499
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
500
-            [$this, 'initialize_db_if_no_migrations_required']
501
-        );
502
-    }
503
-
504
-
505
-    /**
506
-     * If Core detects this addon has been downgraded, you may want to invoke some special logic here.
507
-     */
508
-    public function downgrade()
509
-    {
510
-        $classname = get_class($this);
511
-        do_action("AHEE__{$classname}__downgrade");
512
-        do_action('AHEE__EE_Addon__downgrade', $this);
513
-        // it's possible there's old default data that needs to be double-checked
514
-        add_action(
515
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
516
-            [$this, 'initialize_db_if_no_migrations_required']
517
-        );
518
-    }
519
-
520
-
521
-    /**
522
-     * set_db_update_option_name
523
-     * Until we do something better, we'll just check for migration scripts upon
524
-     * plugin activation only. In the future, we'll want to do it on plugin updates too
525
-     *
526
-     * @return bool
527
-     */
528
-    public function set_db_update_option_name(): bool
529
-    {
530
-        EE_Error::doing_it_wrong(
531
-            __FUNCTION__,
532
-            esc_html__(
533
-                'EE_Addon::set_db_update_option_name was renamed to EE_Addon::set_activation_indicator_option',
534
-                'event_espresso'
535
-            ),
536
-            '4.3.0.alpha.016'
537
-        );
538
-        // let's just handle this on the next request, ok? right now we're just not really ready
539
-        return $this->set_activation_indicator_option();
540
-    }
541
-
542
-
543
-    /**
544
-     * Returns the name of the activation indicator option
545
-     * (an option which is set temporarily to indicate that this addon was just activated)
546
-     *
547
-     * @return string
548
-     * @deprecated since version 4.3.0.alpha.016
549
-     */
550
-    public function get_db_update_option_name(): string
551
-    {
552
-        EE_Error::doing_it_wrong(
553
-            __FUNCTION__,
554
-            esc_html__(
555
-                'EE_Addon::get_db_update_option was renamed to EE_Addon::get_activation_indicator_option_name',
556
-                'event_espresso'
557
-            ),
558
-            '4.3.0.alpha.016'
559
-        );
560
-        return $this->get_activation_indicator_option_name();
561
-    }
562
-
563
-
564
-    /**
565
-     * When the addon is activated, this should be called to set a wordpress option that
566
-     * indicates it was activated. This is especially useful for detecting reactivations.
567
-     *
568
-     * @return bool
569
-     */
570
-    public function set_activation_indicator_option(): bool
571
-    {
572
-        // let's just handle this on the next request, ok? right now we're just not really ready
573
-        return update_option($this->get_activation_indicator_option_name(), true);
574
-    }
575
-
576
-
577
-    /**
578
-     * Gets the name of the wp option which is used to temporarily indicate that this addon was activated
579
-     *
580
-     * @return string
581
-     */
582
-    public function get_activation_indicator_option_name(): string
583
-    {
584
-        return 'ee_activation_' . $this->name();
585
-    }
586
-
587
-
588
-    /**
589
-     * Used by EE_System to set the request type of this addon. Should not be used by addon developers
590
-     *
591
-     * @param int $req_type
592
-     */
593
-    public function set_req_type(int $req_type)
594
-    {
595
-        $this->_req_type = $req_type;
596
-    }
597
-
598
-
599
-    /**
600
-     * Returns the request type of this addon (ie, EE_System::req_type_normal, EE_System::req_type_new_activation,
601
-     * EE_System::req_type_reactivation, EE_System::req_type_upgrade, or EE_System::req_type_downgrade). This is set by
602
-     * EE_System when it is checking for new install or upgrades of addons
603
-     */
604
-    public function detect_req_type($redetect = false): int
605
-    {
606
-        if ($this->_req_type === null || $redetect) {
607
-            $this->detect_activation_or_upgrade();
608
-        }
609
-        return $this->_req_type;
610
-    }
611
-
612
-
613
-    /**
614
-     * Detects the request type for this addon (whether it was just activated, upgrades, a normal request, etc.)
615
-     * Should only be called once per request
616
-     *
617
-     * @return void
618
-     * @throws EE_Error
619
-     */
620
-    public function detect_activation_or_upgrade()
621
-    {
622
-        $activation_history_for_addon = $this->get_activation_history();
623
-        $request_type                 = EE_System::detect_req_type_given_activation_history(
624
-            $activation_history_for_addon,
625
-            $this->get_activation_indicator_option_name(),
626
-            $this->version()
627
-        );
628
-        $this->set_req_type($request_type);
629
-        $classname = get_class($this);
630
-        switch ($request_type) {
631
-            case EE_System::req_type_new_activation:
632
-                do_action("AHEE__{$classname}__detect_activations_or_upgrades__new_activation");
633
-                do_action('AHEE__EE_Addon__detect_activations_or_upgrades__new_activation', $this);
634
-                $this->new_install();
635
-                $this->update_list_of_installed_versions($activation_history_for_addon);
636
-                break;
637
-            case EE_System::req_type_reactivation:
638
-                do_action("AHEE__{$classname}__detect_activations_or_upgrades__reactivation");
639
-                do_action('AHEE__EE_Addon__detect_activations_or_upgrades__reactivation', $this);
640
-                $this->reactivation();
641
-                $this->update_list_of_installed_versions($activation_history_for_addon);
642
-                break;
643
-            case EE_System::req_type_upgrade:
644
-                do_action("AHEE__{$classname}__detect_activations_or_upgrades__upgrade");
645
-                do_action('AHEE__EE_Addon__detect_activations_or_upgrades__upgrade', $this);
646
-                $this->upgrade();
647
-                $this->update_list_of_installed_versions($activation_history_for_addon);
648
-                break;
649
-            case EE_System::req_type_downgrade:
650
-                do_action("AHEE__{$classname}__detect_activations_or_upgrades__downgrade");
651
-                do_action('AHEE__EE_Addon__detect_activations_or_upgrades__downgrade', $this);
652
-                $this->downgrade();
653
-                $this->update_list_of_installed_versions($activation_history_for_addon);
654
-                break;
655
-            case EE_System::req_type_normal:
656
-            default:
657
-                break;
658
-        }
659
-
660
-        do_action("AHEE__{$classname}__detect_if_activation_or_upgrade__complete");
661
-    }
662
-
663
-
664
-    /**
665
-     * Updates the version history for this addon
666
-     *
667
-     * @param array  $version_history
668
-     * @param string $current_version_to_add
669
-     * @return bool success
670
-     */
671
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null): bool
672
-    {
673
-        if (! $version_history) {
674
-            $version_history = $this->get_activation_history();
675
-        }
676
-        if ($current_version_to_add === null) {
677
-            $current_version_to_add = $this->version();
678
-        }
679
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
680
-        return update_option($this->get_activation_history_option_name(), $version_history);
681
-    }
682
-
683
-
684
-    /**
685
-     * Gets the name of the wp option that stores the activation history
686
-     * of this addon
687
-     *
688
-     * @return string
689
-     */
690
-    public function get_activation_history_option_name(): string
691
-    {
692
-        return self::ee_addon_version_history_option_prefix . $this->name();
693
-    }
694
-
695
-
696
-    /**
697
-     * Gets the wp option which stores the activation history for this addon
698
-     *
699
-     * @return array
700
-     */
701
-    public function get_activation_history(): array
702
-    {
703
-        return get_option($this->get_activation_history_option_name(), []);
704
-    }
705
-
706
-
707
-    /**
708
-     * @param string $config_section
709
-     */
710
-    public function set_config_section($config_section = '')
711
-    {
712
-        $this->_config_section = ! empty($config_section) ? $config_section : 'addons';
713
-    }
714
-
715
-
716
-    /**
717
-     * Sets the filepath to the main plugin file
718
-     *
719
-     * @param string $filepath
720
-     */
721
-    public function set_main_plugin_file(string $filepath)
722
-    {
723
-        $this->_main_plugin_file = $filepath;
724
-    }
725
-
726
-
727
-    /**
728
-     * gets the filepath to teh main file
729
-     *
730
-     * @return string
731
-     */
732
-    public function get_main_plugin_file(): string
733
-    {
734
-        return $this->_main_plugin_file;
735
-    }
736
-
737
-
738
-    /**
739
-     * Gets the filename (no path) of the main file (the main file loaded
740
-     * by WP)
741
-     *
742
-     * @return string
743
-     */
744
-    public function get_main_plugin_file_basename(): string
745
-    {
746
-        return plugin_basename($this->get_main_plugin_file());
747
-    }
748
-
749
-
750
-    /**
751
-     * Gets the folder name which contains the main plugin file
752
-     *
753
-     * @return string
754
-     */
755
-    public function get_main_plugin_file_dirname(): string
756
-    {
757
-        return dirname($this->get_main_plugin_file());
758
-    }
759
-
760
-
761
-    /**
762
-     * sets hooks used in the admin
763
-     *
764
-     * @return void
765
-     */
766
-    public function admin_init()
767
-    {
768
-        // is admin and not in M-Mode ?
769
-        if (is_admin() && ! EE_Maintenance_Mode::instance()->level()) {
770
-            add_filter('plugin_action_links', [$this, 'plugin_action_links'], 10, 2);
771
-            add_filter('after_plugin_row_' . $this->_plugin_basename, [$this, 'after_plugin_row'], 10, 3);
772
-        }
773
-    }
774
-
775
-
776
-    /**
777
-     * plugin_actions
778
-     * Add a settings link to the Plugins page, so people can go straight from the plugin page to the settings page.
779
-     *
780
-     * @param array  $links
781
-     * @param string $file
782
-     * @return array
783
-     */
784
-    public function plugin_action_links(array $links, string $file): array
785
-    {
786
-        if ($file === $this->plugin_basename() && $this->plugin_action_slug() !== '') {
787
-            // before other links
788
-            array_unshift(
789
-                $links,
790
-                '<a href="admin.php?page=' . $this->plugin_action_slug() . '">'
791
-                . esc_html__('Settings', 'event_espresso')
792
-                . '</a>'
793
-            );
794
-        }
795
-        return $links;
796
-    }
797
-
798
-
799
-    /**
800
-     * after_plugin_row
801
-     * Add additional content to the plugins page plugin row
802
-     * Inserts another row
803
-     *
804
-     * @param string $plugin_file
805
-     * @param array  $plugin_data
806
-     * @param string $status
807
-     * @return void
808
-     */
809
-    public function after_plugin_row(string $plugin_file, array $plugin_data, string $status)
810
-    {
811
-        $after_plugin_row = '';
812
-        $plugins_page_row = $this->get_plugins_page_row();
813
-        if (! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) {
814
-            $class       = $status ? 'active' : 'inactive';
815
-            $link_text   = isset($plugins_page_row['link_text']) ? $plugins_page_row['link_text'] : '';
816
-            $link_url    = isset($plugins_page_row['link_url']) ? $plugins_page_row['link_url'] : '';
817
-            $description = isset($plugins_page_row['description'])
818
-                ? $plugins_page_row['description']
819
-                : '';
820
-            if (! empty($link_text) && ! empty($link_url) && ! empty($description)) {
821
-                $after_plugin_row .= '<tr id="' . sanitize_title($plugin_file) . '-ee-addon" class="' . $class . '">';
822
-                $after_plugin_row .= '<th class="check-column" scope="row"></th>';
823
-                $after_plugin_row .= '<td class="ee-addon-upsell-info-title-td plugin-title column-primary">';
824
-                $after_plugin_row .= '<p class="ee-addon-upsell-info-dv">
406
+			EEH_Activation::initialize_db_content();
407
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
408
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
409
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
410
+			);
411
+			$rewrite_rules->flushRewriteRules();
412
+			// in case there are lots of addons being activated at once, let's force garbage collection
413
+			// to help avoid memory limit errors
414
+			// EEH_Debug_Tools::instance()->measure_memory( 'db content initialized for ' . get_class( $this), true );
415
+			gc_collect_cycles();
416
+		} else {
417
+			// ask the data migration manager to init this addon's data
418
+			// when migrations are finished because we can't do it now
419
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for($this->name());
420
+		}
421
+	}
422
+
423
+
424
+	/**
425
+	 * Used to setup this addon's database tables, but not necessarily any default
426
+	 * data in them. The default is to actually use the most up-to-date data migration script
427
+	 * for this addon, and just use its schema_changes_before_migration() and schema_changes_after_migration()
428
+	 * methods to setup the db.
429
+	 *
430
+	 * @throws EE_Error
431
+	 * @throws ReflectionException
432
+	 */
433
+	public function initialize_db()
434
+	{
435
+		// find the migration script that sets the database to be compatible with the code
436
+		$current_dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms($this->name());
437
+		if ($current_dms_name) {
438
+			$current_data_migration_script = EE_Registry::instance()->load_dms($current_dms_name);
439
+			$current_data_migration_script->set_migrating(false);
440
+			$current_data_migration_script->schema_changes_before_migration();
441
+			$current_data_migration_script->schema_changes_after_migration();
442
+			if ($current_data_migration_script->get_errors()) {
443
+				foreach ($current_data_migration_script->get_errors() as $error) {
444
+					EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
445
+				}
446
+			}
447
+		}
448
+		// if not DMS was found that should be ok. This addon just doesn't require any database changes
449
+		EE_Data_Migration_Manager::instance()->update_current_database_state_to(
450
+			[
451
+				'slug'    => $this->name(),
452
+				'version' => $this->version(),
453
+			]
454
+		);
455
+	}
456
+
457
+
458
+	/**
459
+	 * If you want to setup default data for the addon, override this method, and call
460
+	 * parent::initialize_default_data() from within it. This is normally called
461
+	 * from EE_Addon::initialize_db_if_no_migrations_required(), just after EE_Addon::initialize_db()
462
+	 * and should verify default data is present (but this is also called
463
+	 * on reactivations and just after migrations, so please verify you actually want
464
+	 * to ADD default data, because it may already be present).
465
+	 * However, please call this parent (currently it just fires a hook which other
466
+	 * addons may be depending on)
467
+	 */
468
+	public function initialize_default_data()
469
+	{
470
+		/**
471
+		 * Called when an addon is ensuring its default data is set (possibly called
472
+		 * on a reactivation, so first check for the absence of other data before setting
473
+		 * default data)
474
+		 *
475
+		 * @param EE_Addon $addon the addon that called this
476
+		 */
477
+		do_action('AHEE__EE_Addon__initialize_default_data__begin', $this);
478
+		// override to insert default data. It is safe to use the models here
479
+		// because the site should not be in maintenance mode
480
+	}
481
+
482
+
483
+	/**
484
+	 * EE Core detected that this addon has been upgraded. We should check if there
485
+	 * are any new migration scripts, and if so put the site into maintenance mode until
486
+	 * they're ran
487
+	 *
488
+	 * @return void
489
+	 * @throws EE_Error
490
+	 */
491
+	public function upgrade()
492
+	{
493
+		$classname = get_class($this);
494
+		do_action("AHEE__{$classname}__upgrade");
495
+		do_action('AHEE__EE_Addon__upgrade', $this);
496
+		EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
497
+		// also it's possible there is new default data that needs to be added
498
+		add_action(
499
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
500
+			[$this, 'initialize_db_if_no_migrations_required']
501
+		);
502
+	}
503
+
504
+
505
+	/**
506
+	 * If Core detects this addon has been downgraded, you may want to invoke some special logic here.
507
+	 */
508
+	public function downgrade()
509
+	{
510
+		$classname = get_class($this);
511
+		do_action("AHEE__{$classname}__downgrade");
512
+		do_action('AHEE__EE_Addon__downgrade', $this);
513
+		// it's possible there's old default data that needs to be double-checked
514
+		add_action(
515
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
516
+			[$this, 'initialize_db_if_no_migrations_required']
517
+		);
518
+	}
519
+
520
+
521
+	/**
522
+	 * set_db_update_option_name
523
+	 * Until we do something better, we'll just check for migration scripts upon
524
+	 * plugin activation only. In the future, we'll want to do it on plugin updates too
525
+	 *
526
+	 * @return bool
527
+	 */
528
+	public function set_db_update_option_name(): bool
529
+	{
530
+		EE_Error::doing_it_wrong(
531
+			__FUNCTION__,
532
+			esc_html__(
533
+				'EE_Addon::set_db_update_option_name was renamed to EE_Addon::set_activation_indicator_option',
534
+				'event_espresso'
535
+			),
536
+			'4.3.0.alpha.016'
537
+		);
538
+		// let's just handle this on the next request, ok? right now we're just not really ready
539
+		return $this->set_activation_indicator_option();
540
+	}
541
+
542
+
543
+	/**
544
+	 * Returns the name of the activation indicator option
545
+	 * (an option which is set temporarily to indicate that this addon was just activated)
546
+	 *
547
+	 * @return string
548
+	 * @deprecated since version 4.3.0.alpha.016
549
+	 */
550
+	public function get_db_update_option_name(): string
551
+	{
552
+		EE_Error::doing_it_wrong(
553
+			__FUNCTION__,
554
+			esc_html__(
555
+				'EE_Addon::get_db_update_option was renamed to EE_Addon::get_activation_indicator_option_name',
556
+				'event_espresso'
557
+			),
558
+			'4.3.0.alpha.016'
559
+		);
560
+		return $this->get_activation_indicator_option_name();
561
+	}
562
+
563
+
564
+	/**
565
+	 * When the addon is activated, this should be called to set a wordpress option that
566
+	 * indicates it was activated. This is especially useful for detecting reactivations.
567
+	 *
568
+	 * @return bool
569
+	 */
570
+	public function set_activation_indicator_option(): bool
571
+	{
572
+		// let's just handle this on the next request, ok? right now we're just not really ready
573
+		return update_option($this->get_activation_indicator_option_name(), true);
574
+	}
575
+
576
+
577
+	/**
578
+	 * Gets the name of the wp option which is used to temporarily indicate that this addon was activated
579
+	 *
580
+	 * @return string
581
+	 */
582
+	public function get_activation_indicator_option_name(): string
583
+	{
584
+		return 'ee_activation_' . $this->name();
585
+	}
586
+
587
+
588
+	/**
589
+	 * Used by EE_System to set the request type of this addon. Should not be used by addon developers
590
+	 *
591
+	 * @param int $req_type
592
+	 */
593
+	public function set_req_type(int $req_type)
594
+	{
595
+		$this->_req_type = $req_type;
596
+	}
597
+
598
+
599
+	/**
600
+	 * Returns the request type of this addon (ie, EE_System::req_type_normal, EE_System::req_type_new_activation,
601
+	 * EE_System::req_type_reactivation, EE_System::req_type_upgrade, or EE_System::req_type_downgrade). This is set by
602
+	 * EE_System when it is checking for new install or upgrades of addons
603
+	 */
604
+	public function detect_req_type($redetect = false): int
605
+	{
606
+		if ($this->_req_type === null || $redetect) {
607
+			$this->detect_activation_or_upgrade();
608
+		}
609
+		return $this->_req_type;
610
+	}
611
+
612
+
613
+	/**
614
+	 * Detects the request type for this addon (whether it was just activated, upgrades, a normal request, etc.)
615
+	 * Should only be called once per request
616
+	 *
617
+	 * @return void
618
+	 * @throws EE_Error
619
+	 */
620
+	public function detect_activation_or_upgrade()
621
+	{
622
+		$activation_history_for_addon = $this->get_activation_history();
623
+		$request_type                 = EE_System::detect_req_type_given_activation_history(
624
+			$activation_history_for_addon,
625
+			$this->get_activation_indicator_option_name(),
626
+			$this->version()
627
+		);
628
+		$this->set_req_type($request_type);
629
+		$classname = get_class($this);
630
+		switch ($request_type) {
631
+			case EE_System::req_type_new_activation:
632
+				do_action("AHEE__{$classname}__detect_activations_or_upgrades__new_activation");
633
+				do_action('AHEE__EE_Addon__detect_activations_or_upgrades__new_activation', $this);
634
+				$this->new_install();
635
+				$this->update_list_of_installed_versions($activation_history_for_addon);
636
+				break;
637
+			case EE_System::req_type_reactivation:
638
+				do_action("AHEE__{$classname}__detect_activations_or_upgrades__reactivation");
639
+				do_action('AHEE__EE_Addon__detect_activations_or_upgrades__reactivation', $this);
640
+				$this->reactivation();
641
+				$this->update_list_of_installed_versions($activation_history_for_addon);
642
+				break;
643
+			case EE_System::req_type_upgrade:
644
+				do_action("AHEE__{$classname}__detect_activations_or_upgrades__upgrade");
645
+				do_action('AHEE__EE_Addon__detect_activations_or_upgrades__upgrade', $this);
646
+				$this->upgrade();
647
+				$this->update_list_of_installed_versions($activation_history_for_addon);
648
+				break;
649
+			case EE_System::req_type_downgrade:
650
+				do_action("AHEE__{$classname}__detect_activations_or_upgrades__downgrade");
651
+				do_action('AHEE__EE_Addon__detect_activations_or_upgrades__downgrade', $this);
652
+				$this->downgrade();
653
+				$this->update_list_of_installed_versions($activation_history_for_addon);
654
+				break;
655
+			case EE_System::req_type_normal:
656
+			default:
657
+				break;
658
+		}
659
+
660
+		do_action("AHEE__{$classname}__detect_if_activation_or_upgrade__complete");
661
+	}
662
+
663
+
664
+	/**
665
+	 * Updates the version history for this addon
666
+	 *
667
+	 * @param array  $version_history
668
+	 * @param string $current_version_to_add
669
+	 * @return bool success
670
+	 */
671
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null): bool
672
+	{
673
+		if (! $version_history) {
674
+			$version_history = $this->get_activation_history();
675
+		}
676
+		if ($current_version_to_add === null) {
677
+			$current_version_to_add = $this->version();
678
+		}
679
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
680
+		return update_option($this->get_activation_history_option_name(), $version_history);
681
+	}
682
+
683
+
684
+	/**
685
+	 * Gets the name of the wp option that stores the activation history
686
+	 * of this addon
687
+	 *
688
+	 * @return string
689
+	 */
690
+	public function get_activation_history_option_name(): string
691
+	{
692
+		return self::ee_addon_version_history_option_prefix . $this->name();
693
+	}
694
+
695
+
696
+	/**
697
+	 * Gets the wp option which stores the activation history for this addon
698
+	 *
699
+	 * @return array
700
+	 */
701
+	public function get_activation_history(): array
702
+	{
703
+		return get_option($this->get_activation_history_option_name(), []);
704
+	}
705
+
706
+
707
+	/**
708
+	 * @param string $config_section
709
+	 */
710
+	public function set_config_section($config_section = '')
711
+	{
712
+		$this->_config_section = ! empty($config_section) ? $config_section : 'addons';
713
+	}
714
+
715
+
716
+	/**
717
+	 * Sets the filepath to the main plugin file
718
+	 *
719
+	 * @param string $filepath
720
+	 */
721
+	public function set_main_plugin_file(string $filepath)
722
+	{
723
+		$this->_main_plugin_file = $filepath;
724
+	}
725
+
726
+
727
+	/**
728
+	 * gets the filepath to teh main file
729
+	 *
730
+	 * @return string
731
+	 */
732
+	public function get_main_plugin_file(): string
733
+	{
734
+		return $this->_main_plugin_file;
735
+	}
736
+
737
+
738
+	/**
739
+	 * Gets the filename (no path) of the main file (the main file loaded
740
+	 * by WP)
741
+	 *
742
+	 * @return string
743
+	 */
744
+	public function get_main_plugin_file_basename(): string
745
+	{
746
+		return plugin_basename($this->get_main_plugin_file());
747
+	}
748
+
749
+
750
+	/**
751
+	 * Gets the folder name which contains the main plugin file
752
+	 *
753
+	 * @return string
754
+	 */
755
+	public function get_main_plugin_file_dirname(): string
756
+	{
757
+		return dirname($this->get_main_plugin_file());
758
+	}
759
+
760
+
761
+	/**
762
+	 * sets hooks used in the admin
763
+	 *
764
+	 * @return void
765
+	 */
766
+	public function admin_init()
767
+	{
768
+		// is admin and not in M-Mode ?
769
+		if (is_admin() && ! EE_Maintenance_Mode::instance()->level()) {
770
+			add_filter('plugin_action_links', [$this, 'plugin_action_links'], 10, 2);
771
+			add_filter('after_plugin_row_' . $this->_plugin_basename, [$this, 'after_plugin_row'], 10, 3);
772
+		}
773
+	}
774
+
775
+
776
+	/**
777
+	 * plugin_actions
778
+	 * Add a settings link to the Plugins page, so people can go straight from the plugin page to the settings page.
779
+	 *
780
+	 * @param array  $links
781
+	 * @param string $file
782
+	 * @return array
783
+	 */
784
+	public function plugin_action_links(array $links, string $file): array
785
+	{
786
+		if ($file === $this->plugin_basename() && $this->plugin_action_slug() !== '') {
787
+			// before other links
788
+			array_unshift(
789
+				$links,
790
+				'<a href="admin.php?page=' . $this->plugin_action_slug() . '">'
791
+				. esc_html__('Settings', 'event_espresso')
792
+				. '</a>'
793
+			);
794
+		}
795
+		return $links;
796
+	}
797
+
798
+
799
+	/**
800
+	 * after_plugin_row
801
+	 * Add additional content to the plugins page plugin row
802
+	 * Inserts another row
803
+	 *
804
+	 * @param string $plugin_file
805
+	 * @param array  $plugin_data
806
+	 * @param string $status
807
+	 * @return void
808
+	 */
809
+	public function after_plugin_row(string $plugin_file, array $plugin_data, string $status)
810
+	{
811
+		$after_plugin_row = '';
812
+		$plugins_page_row = $this->get_plugins_page_row();
813
+		if (! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) {
814
+			$class       = $status ? 'active' : 'inactive';
815
+			$link_text   = isset($plugins_page_row['link_text']) ? $plugins_page_row['link_text'] : '';
816
+			$link_url    = isset($plugins_page_row['link_url']) ? $plugins_page_row['link_url'] : '';
817
+			$description = isset($plugins_page_row['description'])
818
+				? $plugins_page_row['description']
819
+				: '';
820
+			if (! empty($link_text) && ! empty($link_url) && ! empty($description)) {
821
+				$after_plugin_row .= '<tr id="' . sanitize_title($plugin_file) . '-ee-addon" class="' . $class . '">';
822
+				$after_plugin_row .= '<th class="check-column" scope="row"></th>';
823
+				$after_plugin_row .= '<td class="ee-addon-upsell-info-title-td plugin-title column-primary">';
824
+				$after_plugin_row .= '<p class="ee-addon-upsell-info-dv">
825 825
 	                <a class="ee-button" href="' . esc_url_raw($link_url) . '">'
826
-                    . $link_text
827
-                    . ' &nbsp;<span class="dashicons dashicons-arrow-right-alt2" style="margin:0;"></span>'
828
-                    . '</a>
826
+					. $link_text
827
+					. ' &nbsp;<span class="dashicons dashicons-arrow-right-alt2" style="margin:0;"></span>'
828
+					. '</a>
829 829
                 </p>';
830
-                $after_plugin_row .= '</td>';
831
-                $after_plugin_row .= '<td class="ee-addon-upsell-info-desc-td column-description desc">';
832
-                $after_plugin_row .= $description;
833
-                $after_plugin_row .= '</td>';
834
-                $after_plugin_row .= '</tr>';
835
-            } else {
836
-                $after_plugin_row .= $description;
837
-            }
838
-        }
839
-
840
-        echo $after_plugin_row;
841
-    }
842
-
843
-
844
-    /**
845
-     * A safe space for addons to add additional logic like setting hooks that need to be set early in the request.
846
-     * Child classes that have logic like that to run can override this method declaration.  This was not made abstract
847
-     * for back compat reasons.
848
-     *
849
-     * This will fire on the `AHEE__EE_System__load_espresso_addons__complete` hook at priority 999.
850
-     *
851
-     * It is recommended, if client code is `de-registering` an add-on, then do it on the
852
-     * `AHEE__EE_System__load_espresso_addons__complete` hook before priority 999 so as to ensure any code logic in this
853
-     * callback does not get run/set in that request.
854
-     *
855
-     * Also, keep in mind that if a registered add-on happens to be deactivated via
856
-     * EE_System::_deactivate_incompatible_addons() because its incompatible, any code executed in this method
857
-     * (including setting hooks etc) will have executed before the plugin was deactivated.  If you use
858
-     * `after_registration` to set any filter and/or action hooks and want to ensure they are removed on this add-on's
859
-     * deactivation, you can override `EE_Addon::deactivation` and unset your hooks and filters there.  Just remember
860
-     * to call `parent::deactivation`.
861
-     *
862
-     * @since 4.9.26
863
-     */
864
-    public function after_registration()
865
-    {
866
-        // cricket chirp... cricket chirp...
867
-    }
868
-
869
-
870
-    /**
871
-     * @return string
872
-     */
873
-    public function getPueSlug(): string
874
-    {
875
-        return $this->pue_slug;
876
-    }
877
-
878
-
879
-    /**
880
-     * @param string $pue_slug
881
-     */
882
-    public function setPueSlug(string $pue_slug)
883
-    {
884
-        $this->pue_slug = $pue_slug;
885
-    }
830
+				$after_plugin_row .= '</td>';
831
+				$after_plugin_row .= '<td class="ee-addon-upsell-info-desc-td column-description desc">';
832
+				$after_plugin_row .= $description;
833
+				$after_plugin_row .= '</td>';
834
+				$after_plugin_row .= '</tr>';
835
+			} else {
836
+				$after_plugin_row .= $description;
837
+			}
838
+		}
839
+
840
+		echo $after_plugin_row;
841
+	}
842
+
843
+
844
+	/**
845
+	 * A safe space for addons to add additional logic like setting hooks that need to be set early in the request.
846
+	 * Child classes that have logic like that to run can override this method declaration.  This was not made abstract
847
+	 * for back compat reasons.
848
+	 *
849
+	 * This will fire on the `AHEE__EE_System__load_espresso_addons__complete` hook at priority 999.
850
+	 *
851
+	 * It is recommended, if client code is `de-registering` an add-on, then do it on the
852
+	 * `AHEE__EE_System__load_espresso_addons__complete` hook before priority 999 so as to ensure any code logic in this
853
+	 * callback does not get run/set in that request.
854
+	 *
855
+	 * Also, keep in mind that if a registered add-on happens to be deactivated via
856
+	 * EE_System::_deactivate_incompatible_addons() because its incompatible, any code executed in this method
857
+	 * (including setting hooks etc) will have executed before the plugin was deactivated.  If you use
858
+	 * `after_registration` to set any filter and/or action hooks and want to ensure they are removed on this add-on's
859
+	 * deactivation, you can override `EE_Addon::deactivation` and unset your hooks and filters there.  Just remember
860
+	 * to call `parent::deactivation`.
861
+	 *
862
+	 * @since 4.9.26
863
+	 */
864
+	public function after_registration()
865
+	{
866
+		// cricket chirp... cricket chirp...
867
+	}
868
+
869
+
870
+	/**
871
+	 * @return string
872
+	 */
873
+	public function getPueSlug(): string
874
+	{
875
+		return $this->pue_slug;
876
+	}
877
+
878
+
879
+	/**
880
+	 * @param string $pue_slug
881
+	 */
882
+	public function setPueSlug(string $pue_slug)
883
+	{
884
+		$this->pue_slug = $pue_slug;
885
+	}
886 886
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -581,7 +581,7 @@  discard block
 block discarded – undo
581 581
      */
582 582
     public function get_activation_indicator_option_name(): string
583 583
     {
584
-        return 'ee_activation_' . $this->name();
584
+        return 'ee_activation_'.$this->name();
585 585
     }
586 586
 
587 587
 
@@ -670,13 +670,13 @@  discard block
 block discarded – undo
670 670
      */
671 671
     public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null): bool
672 672
     {
673
-        if (! $version_history) {
673
+        if ( ! $version_history) {
674 674
             $version_history = $this->get_activation_history();
675 675
         }
676 676
         if ($current_version_to_add === null) {
677 677
             $current_version_to_add = $this->version();
678 678
         }
679
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
679
+        $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
680 680
         return update_option($this->get_activation_history_option_name(), $version_history);
681 681
     }
682 682
 
@@ -689,7 +689,7 @@  discard block
 block discarded – undo
689 689
      */
690 690
     public function get_activation_history_option_name(): string
691 691
     {
692
-        return self::ee_addon_version_history_option_prefix . $this->name();
692
+        return self::ee_addon_version_history_option_prefix.$this->name();
693 693
     }
694 694
 
695 695
 
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
         // is admin and not in M-Mode ?
769 769
         if (is_admin() && ! EE_Maintenance_Mode::instance()->level()) {
770 770
             add_filter('plugin_action_links', [$this, 'plugin_action_links'], 10, 2);
771
-            add_filter('after_plugin_row_' . $this->_plugin_basename, [$this, 'after_plugin_row'], 10, 3);
771
+            add_filter('after_plugin_row_'.$this->_plugin_basename, [$this, 'after_plugin_row'], 10, 3);
772 772
         }
773 773
     }
774 774
 
@@ -787,7 +787,7 @@  discard block
 block discarded – undo
787 787
             // before other links
788 788
             array_unshift(
789 789
                 $links,
790
-                '<a href="admin.php?page=' . $this->plugin_action_slug() . '">'
790
+                '<a href="admin.php?page='.$this->plugin_action_slug().'">'
791 791
                 . esc_html__('Settings', 'event_espresso')
792 792
                 . '</a>'
793 793
             );
@@ -810,19 +810,19 @@  discard block
 block discarded – undo
810 810
     {
811 811
         $after_plugin_row = '';
812 812
         $plugins_page_row = $this->get_plugins_page_row();
813
-        if (! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) {
813
+        if ( ! empty($plugins_page_row) && $plugin_file === $this->plugin_basename()) {
814 814
             $class       = $status ? 'active' : 'inactive';
815 815
             $link_text   = isset($plugins_page_row['link_text']) ? $plugins_page_row['link_text'] : '';
816 816
             $link_url    = isset($plugins_page_row['link_url']) ? $plugins_page_row['link_url'] : '';
817 817
             $description = isset($plugins_page_row['description'])
818 818
                 ? $plugins_page_row['description']
819 819
                 : '';
820
-            if (! empty($link_text) && ! empty($link_url) && ! empty($description)) {
821
-                $after_plugin_row .= '<tr id="' . sanitize_title($plugin_file) . '-ee-addon" class="' . $class . '">';
820
+            if ( ! empty($link_text) && ! empty($link_url) && ! empty($description)) {
821
+                $after_plugin_row .= '<tr id="'.sanitize_title($plugin_file).'-ee-addon" class="'.$class.'">';
822 822
                 $after_plugin_row .= '<th class="check-column" scope="row"></th>';
823 823
                 $after_plugin_row .= '<td class="ee-addon-upsell-info-title-td plugin-title column-primary">';
824 824
                 $after_plugin_row .= '<p class="ee-addon-upsell-info-dv">
825
-	                <a class="ee-button" href="' . esc_url_raw($link_url) . '">'
825
+	                <a class="ee-button" href="' . esc_url_raw($link_url).'">'
826 826
                     . $link_text
827 827
                     . ' &nbsp;<span class="dashicons dashicons-arrow-right-alt2" style="margin:0;"></span>'
828 828
                     . '</a>
Please login to merge, or discard this patch.
core/domain/values/assets/Asset.php 1 patch
Indentation   +202 added lines, -202 removed lines patch added patch discarded remove patch
@@ -15,206 +15,206 @@
 block discarded – undo
15 15
  */
16 16
 abstract class Asset
17 17
 {
18
-    /**
19
-     * indicates the file extension for a CSS file
20
-     */
21
-    const EXT_CSS = '.css';
22
-
23
-    /**
24
-     * indicates the file extension for a JS file
25
-     */
26
-    const EXT_JS = '.js';
27
-
28
-    /**
29
-     * indicates the file extension for a JS file
30
-     */
31
-    const EXT_PHP = '.php';
32
-
33
-    /**
34
-     * indicates the file extension for a build distribution CSS file
35
-     */
36
-    const FILE_EXTENSION_DISTRIBUTION_CSS = '.dist.css';
37
-
38
-    /**
39
-     * indicates the file extension for a build distribution JS file
40
-     */
41
-    const FILE_EXTENSION_DISTRIBUTION_JS = '.dist.js';
42
-
43
-    /**
44
-     * Indicates the file extension for a build distribution dependencies json file.
45
-     */
46
-    const FILE_EXTENSION_DISTRIBUTION_DEPS = '.dist.deps.php';
47
-
48
-    /**
49
-     * indicates a Cascading Style Sheet asset
50
-     */
51
-    const TYPE_CSS = 'css';
52
-
53
-    /**
54
-     * indicates a Javascript asset
55
-     */
56
-    const TYPE_JS = 'js';
57
-
58
-    /**
59
-     * indicates a JSON asset
60
-     */
61
-    CONST TYPE_JSON = 'json';
62
-    /**
63
-     * indicates a PHP asset
64
-     */
65
-    CONST TYPE_PHP = 'php';
66
-
67
-    /**
68
-     * indicates a Javascript manifest file
69
-     */
70
-    const TYPE_MANIFEST = 'manifest';
71
-
72
-    /**
73
-     * @var DomainInterface $domain
74
-     */
75
-    protected $domain;
76
-
77
-    /**
78
-     * @var string $type
79
-     */
80
-    private $type;
81
-
82
-    /**
83
-     * @var string $handle
84
-     */
85
-    private $handle;
86
-
87
-    /**
88
-     * @var bool $registered
89
-     */
90
-    private $registered = false;
91
-
92
-    /**
93
-     * @var bool $enqueue_immediately
94
-     */
95
-    private $enqueue_immediately = false;
96
-
97
-
98
-    /**
99
-     * Asset constructor.
100
-     *
101
-     * @param                 $type
102
-     * @param string          $handle
103
-     * @param DomainInterface $domain
104
-     * @throws InvalidDataTypeException
105
-     */
106
-    public function __construct($type, $handle, DomainInterface $domain)
107
-    {
108
-        $this->domain = $domain;
109
-        $this->setType($type);
110
-        $this->setHandle($handle);
111
-    }
112
-
113
-
114
-    /**
115
-     * @return array
116
-     */
117
-    public function validAssetTypes()
118
-    {
119
-        return array(
120
-            Asset::TYPE_CSS,
121
-            Asset::TYPE_JS,
122
-            Asset::TYPE_MANIFEST,
123
-        );
124
-    }
125
-
126
-
127
-    /**
128
-     * @param string $type
129
-     * @throws InvalidDataTypeException
130
-     */
131
-    private function setType($type)
132
-    {
133
-        if (! in_array($type, $this->validAssetTypes(), true)) {
134
-            throw new InvalidDataTypeException(
135
-                'Asset::$type',
136
-                $type,
137
-                'one of the TYPE_* class constants on \EventEspresso\core\domain\values\Asset is required'
138
-            );
139
-        }
140
-        $this->type = $type;
141
-    }
142
-
143
-
144
-    /**
145
-     * @param string $handle
146
-     * @throws InvalidDataTypeException
147
-     */
148
-    private function setHandle($handle)
149
-    {
150
-        if (! is_string($handle)) {
151
-            throw new InvalidDataTypeException(
152
-                '$handle',
153
-                $handle,
154
-                'string'
155
-            );
156
-        }
157
-        $this->handle = $handle;
158
-    }
159
-
160
-
161
-    /**
162
-     * @return string
163
-     */
164
-    public function assetNamespace()
165
-    {
166
-        return $this->domain->assetNamespace();
167
-    }
168
-
169
-
170
-    /**
171
-     * @return string
172
-     */
173
-    public function type()
174
-    {
175
-        return $this->type;
176
-    }
177
-
178
-
179
-    /**
180
-     * @return string
181
-     */
182
-    public function handle()
183
-    {
184
-        return $this->handle;
185
-    }
186
-
187
-    /**
188
-     * @return bool
189
-     */
190
-    public function isRegistered()
191
-    {
192
-        return $this->registered;
193
-    }
194
-
195
-    /**
196
-     * @param bool $registered
197
-     */
198
-    public function setRegistered($registered = true)
199
-    {
200
-        $this->registered = filter_var($registered, FILTER_VALIDATE_BOOLEAN);
201
-    }
202
-
203
-
204
-    /**
205
-     * @return bool
206
-     */
207
-    public function enqueueImmediately()
208
-    {
209
-        return $this->enqueue_immediately;
210
-    }
211
-
212
-
213
-    /**
214
-     * @param bool $enqueue_immediately
215
-     */
216
-    public function setEnqueueImmediately($enqueue_immediately = true)
217
-    {
218
-        $this->enqueue_immediately = filter_var($enqueue_immediately, FILTER_VALIDATE_BOOLEAN);
219
-    }
18
+	/**
19
+	 * indicates the file extension for a CSS file
20
+	 */
21
+	const EXT_CSS = '.css';
22
+
23
+	/**
24
+	 * indicates the file extension for a JS file
25
+	 */
26
+	const EXT_JS = '.js';
27
+
28
+	/**
29
+	 * indicates the file extension for a JS file
30
+	 */
31
+	const EXT_PHP = '.php';
32
+
33
+	/**
34
+	 * indicates the file extension for a build distribution CSS file
35
+	 */
36
+	const FILE_EXTENSION_DISTRIBUTION_CSS = '.dist.css';
37
+
38
+	/**
39
+	 * indicates the file extension for a build distribution JS file
40
+	 */
41
+	const FILE_EXTENSION_DISTRIBUTION_JS = '.dist.js';
42
+
43
+	/**
44
+	 * Indicates the file extension for a build distribution dependencies json file.
45
+	 */
46
+	const FILE_EXTENSION_DISTRIBUTION_DEPS = '.dist.deps.php';
47
+
48
+	/**
49
+	 * indicates a Cascading Style Sheet asset
50
+	 */
51
+	const TYPE_CSS = 'css';
52
+
53
+	/**
54
+	 * indicates a Javascript asset
55
+	 */
56
+	const TYPE_JS = 'js';
57
+
58
+	/**
59
+	 * indicates a JSON asset
60
+	 */
61
+	CONST TYPE_JSON = 'json';
62
+	/**
63
+	 * indicates a PHP asset
64
+	 */
65
+	CONST TYPE_PHP = 'php';
66
+
67
+	/**
68
+	 * indicates a Javascript manifest file
69
+	 */
70
+	const TYPE_MANIFEST = 'manifest';
71
+
72
+	/**
73
+	 * @var DomainInterface $domain
74
+	 */
75
+	protected $domain;
76
+
77
+	/**
78
+	 * @var string $type
79
+	 */
80
+	private $type;
81
+
82
+	/**
83
+	 * @var string $handle
84
+	 */
85
+	private $handle;
86
+
87
+	/**
88
+	 * @var bool $registered
89
+	 */
90
+	private $registered = false;
91
+
92
+	/**
93
+	 * @var bool $enqueue_immediately
94
+	 */
95
+	private $enqueue_immediately = false;
96
+
97
+
98
+	/**
99
+	 * Asset constructor.
100
+	 *
101
+	 * @param                 $type
102
+	 * @param string          $handle
103
+	 * @param DomainInterface $domain
104
+	 * @throws InvalidDataTypeException
105
+	 */
106
+	public function __construct($type, $handle, DomainInterface $domain)
107
+	{
108
+		$this->domain = $domain;
109
+		$this->setType($type);
110
+		$this->setHandle($handle);
111
+	}
112
+
113
+
114
+	/**
115
+	 * @return array
116
+	 */
117
+	public function validAssetTypes()
118
+	{
119
+		return array(
120
+			Asset::TYPE_CSS,
121
+			Asset::TYPE_JS,
122
+			Asset::TYPE_MANIFEST,
123
+		);
124
+	}
125
+
126
+
127
+	/**
128
+	 * @param string $type
129
+	 * @throws InvalidDataTypeException
130
+	 */
131
+	private function setType($type)
132
+	{
133
+		if (! in_array($type, $this->validAssetTypes(), true)) {
134
+			throw new InvalidDataTypeException(
135
+				'Asset::$type',
136
+				$type,
137
+				'one of the TYPE_* class constants on \EventEspresso\core\domain\values\Asset is required'
138
+			);
139
+		}
140
+		$this->type = $type;
141
+	}
142
+
143
+
144
+	/**
145
+	 * @param string $handle
146
+	 * @throws InvalidDataTypeException
147
+	 */
148
+	private function setHandle($handle)
149
+	{
150
+		if (! is_string($handle)) {
151
+			throw new InvalidDataTypeException(
152
+				'$handle',
153
+				$handle,
154
+				'string'
155
+			);
156
+		}
157
+		$this->handle = $handle;
158
+	}
159
+
160
+
161
+	/**
162
+	 * @return string
163
+	 */
164
+	public function assetNamespace()
165
+	{
166
+		return $this->domain->assetNamespace();
167
+	}
168
+
169
+
170
+	/**
171
+	 * @return string
172
+	 */
173
+	public function type()
174
+	{
175
+		return $this->type;
176
+	}
177
+
178
+
179
+	/**
180
+	 * @return string
181
+	 */
182
+	public function handle()
183
+	{
184
+		return $this->handle;
185
+	}
186
+
187
+	/**
188
+	 * @return bool
189
+	 */
190
+	public function isRegistered()
191
+	{
192
+		return $this->registered;
193
+	}
194
+
195
+	/**
196
+	 * @param bool $registered
197
+	 */
198
+	public function setRegistered($registered = true)
199
+	{
200
+		$this->registered = filter_var($registered, FILTER_VALIDATE_BOOLEAN);
201
+	}
202
+
203
+
204
+	/**
205
+	 * @return bool
206
+	 */
207
+	public function enqueueImmediately()
208
+	{
209
+		return $this->enqueue_immediately;
210
+	}
211
+
212
+
213
+	/**
214
+	 * @param bool $enqueue_immediately
215
+	 */
216
+	public function setEnqueueImmediately($enqueue_immediately = true)
217
+	{
218
+		$this->enqueue_immediately = filter_var($enqueue_immediately, FILTER_VALIDATE_BOOLEAN);
219
+	}
220 220
 }
Please login to merge, or discard this patch.
core/services/shortcodes/LegacyShortcodesManager.php 1 patch
Indentation   +440 added lines, -440 removed lines patch added patch discarded remove patch
@@ -25,444 +25,444 @@
 block discarded – undo
25 25
  */
26 26
 class LegacyShortcodesManager
27 27
 {
28
-    /**
29
-     * @type CurrentPage
30
-     */
31
-    protected $current_page;
32
-
33
-    /**
34
-     * @var EE_Registry $registry
35
-     */
36
-    private $registry;
37
-
38
-
39
-    /**
40
-     * LegacyShortcodesManager constructor.
41
-     *
42
-     * @param EE_Registry $registry
43
-     * @param CurrentPage $current_page
44
-     */
45
-    public function __construct(EE_Registry $registry, CurrentPage $current_page)
46
-    {
47
-        $this->registry = $registry;
48
-        $this->current_page = $current_page;
49
-    }
50
-
51
-
52
-    /**
53
-     * @return EE_Registry
54
-     */
55
-    public function registry()
56
-    {
57
-        return $this->registry;
58
-    }
59
-
60
-
61
-    /**
62
-     * registerShortcodes
63
-     *
64
-     * @return void
65
-     */
66
-    public function registerShortcodes()
67
-    {
68
-        $this->registry->shortcodes = $this->getShortcodes();
69
-    }
70
-
71
-
72
-    /**
73
-     * getShortcodes
74
-     *
75
-     * @return array
76
-     */
77
-    public function getShortcodes()
78
-    {
79
-        // previously this method would glob the shortcodes directory
80
-        // then filter that list of shortcodes to register,
81
-        // but now we are going to just supply an empty array.
82
-        // this allows any shortcodes that have not yet been converted to the new system
83
-        // to still get loaded and processed, albeit using the same legacy logic as before
84
-        $shortcodes_to_register = apply_filters(
85
-            'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
86
-            array()
87
-        );
88
-        if (! empty($shortcodes_to_register)) {
89
-            // cycle thru shortcode folders
90
-            foreach ($shortcodes_to_register as $shortcode_path) {
91
-                // add to list of installed shortcode modules
92
-                $this->registerShortcode($shortcode_path);
93
-            }
94
-        }
95
-        // filter list of installed modules
96
-        return apply_filters(
97
-            'FHEE__EE_Config___register_shortcodes__installed_shortcodes',
98
-            ! empty($this->registry->shortcodes)
99
-                ? $this->registry->shortcodes
100
-                : array()
101
-        );
102
-    }
103
-
104
-
105
-    /**
106
-     * register_shortcode - makes core aware of this shortcode
107
-     *
108
-     * @param    string $shortcode_path - full path up to and including shortcode folder
109
-     * @return    bool
110
-     */
111
-    public function registerShortcode($shortcode_path = null)
112
-    {
113
-        do_action('AHEE__EE_Config__register_shortcode__begin', $shortcode_path);
114
-        $shortcode_ext = '.shortcode.php';
115
-        // make all separators match
116
-        $shortcode_path = str_replace(array('\\', '/'), '/', $shortcode_path);
117
-        // does the file path INCLUDE the actual file name as part of the path ?
118
-        if (strpos($shortcode_path, $shortcode_ext) !== false) {
119
-            // grab shortcode file name from directory name and break apart at dots
120
-            $shortcode_file = explode('.', basename($shortcode_path));
121
-            // take first segment from file name pieces and remove class prefix if it exists
122
-            $shortcode = strpos($shortcode_file[0], 'EES_') === 0
123
-                ? substr($shortcode_file[0], 4)
124
-                : $shortcode_file[0];
125
-            // sanitize shortcode directory name
126
-            $shortcode = sanitize_key($shortcode);
127
-            // now we need to rebuild the shortcode path
128
-            $shortcode_path = explode('/', $shortcode_path);
129
-            // remove last segment
130
-            array_pop($shortcode_path);
131
-            // glue it back together
132
-            $shortcode_path = implode('/', $shortcode_path) . '/';
133
-        } else {
134
-            // we need to generate the filename based off of the folder name
135
-            // grab and sanitize shortcode directory name
136
-            $shortcode = sanitize_key(basename($shortcode_path));
137
-            $shortcode_path = rtrim($shortcode_path, '/') . '/';
138
-        }
139
-        // create classname from shortcode directory or file name
140
-        $shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
141
-        // add class prefix
142
-        $shortcode_class = 'EES_' . $shortcode;
143
-        // does the shortcode exist ?
144
-        if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
145
-            $msg = sprintf(
146
-                esc_html__(
147
-                    'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
148
-                    'event_espresso'
149
-                ),
150
-                $shortcode_class,
151
-                $shortcode_path . '/' . $shortcode_class . $shortcode_ext
152
-            );
153
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
154
-            return false;
155
-        }
156
-        // load the shortcode class file
157
-        require_once($shortcode_path . $shortcode_class . $shortcode_ext);
158
-        // verify that class exists
159
-        if (! class_exists($shortcode_class)) {
160
-            $msg = sprintf(
161
-                esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
162
-                $shortcode_class
163
-            );
164
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
165
-            return false;
166
-        }
167
-        $shortcode = strtoupper($shortcode);
168
-        // add to array of registered shortcodes
169
-        $this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
170
-        return true;
171
-    }
172
-
173
-
174
-    /**
175
-     *    _initialize_shortcodes
176
-     *    allow shortcodes to set hooks for the rest of the system
177
-     *
178
-     * @return void
179
-     */
180
-    public function addShortcodes()
181
-    {
182
-        // cycle thru shortcode folders
183
-        foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
184
-            // add class prefix
185
-            $shortcode_class = 'EES_' . $shortcode;
186
-            // fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
187
-            // which set hooks ?
188
-            if (is_admin()) {
189
-                // fire immediately
190
-                call_user_func(array($shortcode_class, 'set_hooks_admin'));
191
-            } else {
192
-                // delay until other systems are online
193
-                add_action(
194
-                    'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
195
-                    array($shortcode_class, 'set_hooks')
196
-                );
197
-                // convert classname to UPPERCASE and create WP shortcode.
198
-                $shortcode_tag = strtoupper($shortcode);
199
-                // but first check if the shortcode has already
200
-                // been added before assigning 'fallback_shortcode_processor'
201
-                if (! shortcode_exists($shortcode_tag)) {
202
-                    // NOTE: this shortcode declaration will get overridden if the shortcode
203
-                    // is successfully detected in the post content in initializeShortcode()
204
-                    add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
205
-                }
206
-            }
207
-        }
208
-    }
209
-
210
-
211
-    /**
212
-     * callback for the WP "get_header" hook point
213
-     * checks posts for EE shortcodes, and initializes them,
214
-     * then toggles filter switch that loads core default assets
215
-     *
216
-     * @param WP_Query $wp_query
217
-     * @return void
218
-     * @throws ReflectionException
219
-     */
220
-    public function initializeShortcodes(WP_Query $wp_query)
221
-    {
222
-        if (
223
-            empty($this->registry->shortcodes)
224
-            || defined('EE_TESTS_DIR')
225
-            || ! $wp_query->is_main_query()
226
-            || is_admin()
227
-        ) {
228
-            return;
229
-        }
230
-        // in case shortcode is loaded unexpectedly and deps haven't been set up correctly
231
-        EE_Dependency_Map::register_dependencies(
232
-            'EE_Front_Controller',
233
-            [
234
-                'EE_Registry' => EE_Dependency_Map::load_from_cache,
235
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
236
-                'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
237
-            ]
238
-        );
239
-        global $wp;
240
-        /** @var EE_Front_controller $Front_Controller */
241
-        $Front_Controller = LoaderFactory::getLoader()->getShared('EE_Front_Controller');
242
-        do_action('AHEE__EE_Front_Controller__initialize_shortcodes__begin', $wp, $Front_Controller);
243
-        $this->current_page->parseQueryVars();
244
-        // grab post_name from request
245
-        $current_post = apply_filters(
246
-            'FHEE__EE_Front_Controller__initialize_shortcodes__current_post_name',
247
-            $this->current_page->postName()
248
-        );
249
-        $show_on_front = get_option('show_on_front');
250
-        // if it's not set, then check if frontpage is blog
251
-        if (empty($current_post)) {
252
-            // yup.. this is the posts page, prepare to load all shortcode modules
253
-            $current_post = 'posts';
254
-            // unless..
255
-            if ($show_on_front === 'page') {
256
-                // some other page is set as the homepage
257
-                $page_on_front = get_option('page_on_front');
258
-                if ($page_on_front) {
259
-                    // k now we need to find the post_name for this page
260
-                    global $wpdb;
261
-                    $page_on_front = $wpdb->get_var(
262
-                        $wpdb->prepare(
263
-                            "SELECT post_name from {$wpdb->posts} WHERE post_type='page' AND post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d",
264
-                            $page_on_front
265
-                        )
266
-                    );
267
-                    // set the current post slug to what it actually is
268
-                    $current_post = $page_on_front ?: $current_post;
269
-                }
270
-            }
271
-        }
272
-        // in case $current_post is hierarchical like: /parent-page/current-page
273
-        $current_post = basename($current_post);
274
-        if (
275
-            // is current page/post the "blog" page ?
276
-            $current_post === EE_Config::get_page_for_posts()
277
-            // or are we on a category page?
278
-            || (
279
-                is_array(term_exists($current_post, 'category'))
280
-                || array_key_exists('category_name', $wp->query_vars)
281
-            )
282
-        ) {
283
-            // initialize all legacy shortcodes
284
-            $load_assets = $this->parseContentForShortcodes('', true);
285
-        } else {
286
-            global $post;
287
-            if ($post instanceof WP_Post) {
288
-                $post_content = $post->post_content;
289
-            } else {
290
-                global $wpdb;
291
-                $post_content = $wpdb->get_var(
292
-                    $wpdb->prepare(
293
-                        "SELECT post_content from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s",
294
-                        $current_post
295
-                    )
296
-                );
297
-            }
298
-            $load_assets = $this->parseContentForShortcodes($post_content);
299
-        }
300
-        if ($load_assets) {
301
-            $this->current_page->setEspressoPage(true);
302
-            add_filter('FHEE_load_css', '__return_true');
303
-            add_filter('FHEE_load_js', '__return_true');
304
-        }
305
-        do_action('AHEE__EE_Front_Controller__initialize_shortcodes__end', $Front_Controller);
306
-    }
307
-
308
-
309
-    /**
310
-     * checks supplied content against list of legacy shortcodes,
311
-     * then initializes any found shortcodes, and returns true.
312
-     * returns false if no shortcodes found.
313
-     *
314
-     * @param string $content
315
-     * @param bool   $load_all if true, then ALL active legacy shortcodes will be initialized
316
-     * @return bool
317
-     * @throws ReflectionException
318
-     */
319
-    public function parseContentForShortcodes($content = '', $load_all = false)
320
-    {
321
-        $has_shortcode = false;
322
-        foreach ($this->registry->shortcodes as $shortcode_class => $shortcode) {
323
-            if ($load_all || has_shortcode($content, $shortcode_class)) {
324
-                // load up the shortcode
325
-                $this->initializeShortcode($shortcode_class);
326
-                $has_shortcode = true;
327
-            }
328
-        }
329
-        // one last test for an [espresso_*] shortcode
330
-        if (! $has_shortcode) {
331
-            $has_shortcode = strpos($content, '[espresso_') !== false;
332
-        }
333
-        return $has_shortcode;
334
-    }
335
-
336
-
337
-    /**
338
-     * given a shortcode name, will instantiate the shortcode and call it's run() method
339
-     *
340
-     * @param string $shortcode_class
341
-     * @param WP     $wp
342
-     * @throws ReflectionException
343
-     */
344
-    public function initializeShortcode($shortcode_class = '', WP $wp = null)
345
-    {
346
-        // don't do anything if shortcode is already initialized
347
-        if (
348
-            empty($this->registry->shortcodes->{$shortcode_class})
349
-            || ! is_string($this->registry->shortcodes->{$shortcode_class})
350
-        ) {
351
-            return;
352
-        }
353
-        // let's pause to reflect on this...
354
-        $sc_reflector = new ReflectionClass(LegacyShortcodesManager::addShortcodeClassPrefix($shortcode_class));
355
-        // ensure that class is actually a shortcode
356
-        if (
357
-            defined('WP_DEBUG')
358
-            && WP_DEBUG === true
359
-            && ! $sc_reflector->isSubclassOf('EES_Shortcode')
360
-        ) {
361
-            EE_Error::add_error(
362
-                sprintf(
363
-                    esc_html__(
364
-                        'The requested %s shortcode is not of the class "EES_Shortcode". Please check your files.',
365
-                        'event_espresso'
366
-                    ),
367
-                    $shortcode_class
368
-                ),
369
-                __FILE__,
370
-                __FUNCTION__,
371
-                __LINE__
372
-            );
373
-            add_filter('FHEE_run_EE_the_content', '__return_true');
374
-            return;
375
-        }
376
-        global $wp;
377
-        // and pass the request object to the run method
378
-        $this->registry->shortcodes->{$shortcode_class} = $sc_reflector->newInstance();
379
-        // fire the shortcode class's run method, so that it can activate resources
380
-        $this->registry->shortcodes->{$shortcode_class}->run($wp);
381
-    }
382
-
383
-
384
-    /**
385
-     * get classname, remove EES_prefix, and convert to UPPERCASE
386
-     *
387
-     * @param string $class_name
388
-     * @return string
389
-     */
390
-    public static function generateShortcodeTagFromClassName($class_name)
391
-    {
392
-        return strtoupper(str_replace('EES_', '', $class_name));
393
-    }
394
-
395
-
396
-    /**
397
-     * add EES_prefix and Capitalize words
398
-     *
399
-     * @param string $tag
400
-     * @return string
401
-     */
402
-    public static function generateShortcodeClassNameFromTag($tag)
403
-    {
404
-        // order of operation runs from inside to out
405
-        // 5) maybe add prefix
406
-        return LegacyShortcodesManager::addShortcodeClassPrefix(
407
-            // 4) find spaces, replace with underscores
408
-            str_replace(
409
-                ' ',
410
-                '_',
411
-                // 3) capitalize first letter of each word
412
-                ucwords(
413
-                    // 2) also change to lowercase so ucwords() will work
414
-                    strtolower(
415
-                        // 1) find underscores, replace with spaces so ucwords() will work
416
-                        str_replace(
417
-                            '_',
418
-                            ' ',
419
-                            $tag
420
-                        )
421
-                    )
422
-                )
423
-            )
424
-        );
425
-    }
426
-
427
-
428
-    /**
429
-     * maybe add EES_prefix
430
-     *
431
-     * @param string $class_name
432
-     * @return string
433
-     */
434
-    public static function addShortcodeClassPrefix($class_name)
435
-    {
436
-        return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
437
-    }
438
-
439
-
440
-    /**
441
-     * @return array
442
-     */
443
-    public function getEspressoShortcodeTags()
444
-    {
445
-        static $shortcode_tags = array();
446
-        if (empty($shortcode_tags)) {
447
-            $shortcode_tags = array_keys((array) $this->registry->shortcodes);
448
-        }
449
-        return $shortcode_tags;
450
-    }
451
-
452
-
453
-    /**
454
-     * @param string $content
455
-     * @return string
456
-     * @throws ReflectionException
457
-     */
458
-    public function doShortcode($content)
459
-    {
460
-        foreach ($this->getEspressoShortcodeTags() as $shortcode_tag) {
461
-            if (strpos($content, $shortcode_tag) !== false) {
462
-                $shortcode_class = LegacyShortcodesManager::generateShortcodeClassNameFromTag($shortcode_tag);
463
-                $this->initializeShortcode($shortcode_class);
464
-            }
465
-        }
466
-        return do_shortcode($content);
467
-    }
28
+	/**
29
+	 * @type CurrentPage
30
+	 */
31
+	protected $current_page;
32
+
33
+	/**
34
+	 * @var EE_Registry $registry
35
+	 */
36
+	private $registry;
37
+
38
+
39
+	/**
40
+	 * LegacyShortcodesManager constructor.
41
+	 *
42
+	 * @param EE_Registry $registry
43
+	 * @param CurrentPage $current_page
44
+	 */
45
+	public function __construct(EE_Registry $registry, CurrentPage $current_page)
46
+	{
47
+		$this->registry = $registry;
48
+		$this->current_page = $current_page;
49
+	}
50
+
51
+
52
+	/**
53
+	 * @return EE_Registry
54
+	 */
55
+	public function registry()
56
+	{
57
+		return $this->registry;
58
+	}
59
+
60
+
61
+	/**
62
+	 * registerShortcodes
63
+	 *
64
+	 * @return void
65
+	 */
66
+	public function registerShortcodes()
67
+	{
68
+		$this->registry->shortcodes = $this->getShortcodes();
69
+	}
70
+
71
+
72
+	/**
73
+	 * getShortcodes
74
+	 *
75
+	 * @return array
76
+	 */
77
+	public function getShortcodes()
78
+	{
79
+		// previously this method would glob the shortcodes directory
80
+		// then filter that list of shortcodes to register,
81
+		// but now we are going to just supply an empty array.
82
+		// this allows any shortcodes that have not yet been converted to the new system
83
+		// to still get loaded and processed, albeit using the same legacy logic as before
84
+		$shortcodes_to_register = apply_filters(
85
+			'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
86
+			array()
87
+		);
88
+		if (! empty($shortcodes_to_register)) {
89
+			// cycle thru shortcode folders
90
+			foreach ($shortcodes_to_register as $shortcode_path) {
91
+				// add to list of installed shortcode modules
92
+				$this->registerShortcode($shortcode_path);
93
+			}
94
+		}
95
+		// filter list of installed modules
96
+		return apply_filters(
97
+			'FHEE__EE_Config___register_shortcodes__installed_shortcodes',
98
+			! empty($this->registry->shortcodes)
99
+				? $this->registry->shortcodes
100
+				: array()
101
+		);
102
+	}
103
+
104
+
105
+	/**
106
+	 * register_shortcode - makes core aware of this shortcode
107
+	 *
108
+	 * @param    string $shortcode_path - full path up to and including shortcode folder
109
+	 * @return    bool
110
+	 */
111
+	public function registerShortcode($shortcode_path = null)
112
+	{
113
+		do_action('AHEE__EE_Config__register_shortcode__begin', $shortcode_path);
114
+		$shortcode_ext = '.shortcode.php';
115
+		// make all separators match
116
+		$shortcode_path = str_replace(array('\\', '/'), '/', $shortcode_path);
117
+		// does the file path INCLUDE the actual file name as part of the path ?
118
+		if (strpos($shortcode_path, $shortcode_ext) !== false) {
119
+			// grab shortcode file name from directory name and break apart at dots
120
+			$shortcode_file = explode('.', basename($shortcode_path));
121
+			// take first segment from file name pieces and remove class prefix if it exists
122
+			$shortcode = strpos($shortcode_file[0], 'EES_') === 0
123
+				? substr($shortcode_file[0], 4)
124
+				: $shortcode_file[0];
125
+			// sanitize shortcode directory name
126
+			$shortcode = sanitize_key($shortcode);
127
+			// now we need to rebuild the shortcode path
128
+			$shortcode_path = explode('/', $shortcode_path);
129
+			// remove last segment
130
+			array_pop($shortcode_path);
131
+			// glue it back together
132
+			$shortcode_path = implode('/', $shortcode_path) . '/';
133
+		} else {
134
+			// we need to generate the filename based off of the folder name
135
+			// grab and sanitize shortcode directory name
136
+			$shortcode = sanitize_key(basename($shortcode_path));
137
+			$shortcode_path = rtrim($shortcode_path, '/') . '/';
138
+		}
139
+		// create classname from shortcode directory or file name
140
+		$shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
141
+		// add class prefix
142
+		$shortcode_class = 'EES_' . $shortcode;
143
+		// does the shortcode exist ?
144
+		if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
145
+			$msg = sprintf(
146
+				esc_html__(
147
+					'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
148
+					'event_espresso'
149
+				),
150
+				$shortcode_class,
151
+				$shortcode_path . '/' . $shortcode_class . $shortcode_ext
152
+			);
153
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
154
+			return false;
155
+		}
156
+		// load the shortcode class file
157
+		require_once($shortcode_path . $shortcode_class . $shortcode_ext);
158
+		// verify that class exists
159
+		if (! class_exists($shortcode_class)) {
160
+			$msg = sprintf(
161
+				esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
162
+				$shortcode_class
163
+			);
164
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
165
+			return false;
166
+		}
167
+		$shortcode = strtoupper($shortcode);
168
+		// add to array of registered shortcodes
169
+		$this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
170
+		return true;
171
+	}
172
+
173
+
174
+	/**
175
+	 *    _initialize_shortcodes
176
+	 *    allow shortcodes to set hooks for the rest of the system
177
+	 *
178
+	 * @return void
179
+	 */
180
+	public function addShortcodes()
181
+	{
182
+		// cycle thru shortcode folders
183
+		foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
184
+			// add class prefix
185
+			$shortcode_class = 'EES_' . $shortcode;
186
+			// fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
187
+			// which set hooks ?
188
+			if (is_admin()) {
189
+				// fire immediately
190
+				call_user_func(array($shortcode_class, 'set_hooks_admin'));
191
+			} else {
192
+				// delay until other systems are online
193
+				add_action(
194
+					'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
195
+					array($shortcode_class, 'set_hooks')
196
+				);
197
+				// convert classname to UPPERCASE and create WP shortcode.
198
+				$shortcode_tag = strtoupper($shortcode);
199
+				// but first check if the shortcode has already
200
+				// been added before assigning 'fallback_shortcode_processor'
201
+				if (! shortcode_exists($shortcode_tag)) {
202
+					// NOTE: this shortcode declaration will get overridden if the shortcode
203
+					// is successfully detected in the post content in initializeShortcode()
204
+					add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
205
+				}
206
+			}
207
+		}
208
+	}
209
+
210
+
211
+	/**
212
+	 * callback for the WP "get_header" hook point
213
+	 * checks posts for EE shortcodes, and initializes them,
214
+	 * then toggles filter switch that loads core default assets
215
+	 *
216
+	 * @param WP_Query $wp_query
217
+	 * @return void
218
+	 * @throws ReflectionException
219
+	 */
220
+	public function initializeShortcodes(WP_Query $wp_query)
221
+	{
222
+		if (
223
+			empty($this->registry->shortcodes)
224
+			|| defined('EE_TESTS_DIR')
225
+			|| ! $wp_query->is_main_query()
226
+			|| is_admin()
227
+		) {
228
+			return;
229
+		}
230
+		// in case shortcode is loaded unexpectedly and deps haven't been set up correctly
231
+		EE_Dependency_Map::register_dependencies(
232
+			'EE_Front_Controller',
233
+			[
234
+				'EE_Registry' => EE_Dependency_Map::load_from_cache,
235
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
236
+				'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
237
+			]
238
+		);
239
+		global $wp;
240
+		/** @var EE_Front_controller $Front_Controller */
241
+		$Front_Controller = LoaderFactory::getLoader()->getShared('EE_Front_Controller');
242
+		do_action('AHEE__EE_Front_Controller__initialize_shortcodes__begin', $wp, $Front_Controller);
243
+		$this->current_page->parseQueryVars();
244
+		// grab post_name from request
245
+		$current_post = apply_filters(
246
+			'FHEE__EE_Front_Controller__initialize_shortcodes__current_post_name',
247
+			$this->current_page->postName()
248
+		);
249
+		$show_on_front = get_option('show_on_front');
250
+		// if it's not set, then check if frontpage is blog
251
+		if (empty($current_post)) {
252
+			// yup.. this is the posts page, prepare to load all shortcode modules
253
+			$current_post = 'posts';
254
+			// unless..
255
+			if ($show_on_front === 'page') {
256
+				// some other page is set as the homepage
257
+				$page_on_front = get_option('page_on_front');
258
+				if ($page_on_front) {
259
+					// k now we need to find the post_name for this page
260
+					global $wpdb;
261
+					$page_on_front = $wpdb->get_var(
262
+						$wpdb->prepare(
263
+							"SELECT post_name from {$wpdb->posts} WHERE post_type='page' AND post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d",
264
+							$page_on_front
265
+						)
266
+					);
267
+					// set the current post slug to what it actually is
268
+					$current_post = $page_on_front ?: $current_post;
269
+				}
270
+			}
271
+		}
272
+		// in case $current_post is hierarchical like: /parent-page/current-page
273
+		$current_post = basename($current_post);
274
+		if (
275
+			// is current page/post the "blog" page ?
276
+			$current_post === EE_Config::get_page_for_posts()
277
+			// or are we on a category page?
278
+			|| (
279
+				is_array(term_exists($current_post, 'category'))
280
+				|| array_key_exists('category_name', $wp->query_vars)
281
+			)
282
+		) {
283
+			// initialize all legacy shortcodes
284
+			$load_assets = $this->parseContentForShortcodes('', true);
285
+		} else {
286
+			global $post;
287
+			if ($post instanceof WP_Post) {
288
+				$post_content = $post->post_content;
289
+			} else {
290
+				global $wpdb;
291
+				$post_content = $wpdb->get_var(
292
+					$wpdb->prepare(
293
+						"SELECT post_content from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s",
294
+						$current_post
295
+					)
296
+				);
297
+			}
298
+			$load_assets = $this->parseContentForShortcodes($post_content);
299
+		}
300
+		if ($load_assets) {
301
+			$this->current_page->setEspressoPage(true);
302
+			add_filter('FHEE_load_css', '__return_true');
303
+			add_filter('FHEE_load_js', '__return_true');
304
+		}
305
+		do_action('AHEE__EE_Front_Controller__initialize_shortcodes__end', $Front_Controller);
306
+	}
307
+
308
+
309
+	/**
310
+	 * checks supplied content against list of legacy shortcodes,
311
+	 * then initializes any found shortcodes, and returns true.
312
+	 * returns false if no shortcodes found.
313
+	 *
314
+	 * @param string $content
315
+	 * @param bool   $load_all if true, then ALL active legacy shortcodes will be initialized
316
+	 * @return bool
317
+	 * @throws ReflectionException
318
+	 */
319
+	public function parseContentForShortcodes($content = '', $load_all = false)
320
+	{
321
+		$has_shortcode = false;
322
+		foreach ($this->registry->shortcodes as $shortcode_class => $shortcode) {
323
+			if ($load_all || has_shortcode($content, $shortcode_class)) {
324
+				// load up the shortcode
325
+				$this->initializeShortcode($shortcode_class);
326
+				$has_shortcode = true;
327
+			}
328
+		}
329
+		// one last test for an [espresso_*] shortcode
330
+		if (! $has_shortcode) {
331
+			$has_shortcode = strpos($content, '[espresso_') !== false;
332
+		}
333
+		return $has_shortcode;
334
+	}
335
+
336
+
337
+	/**
338
+	 * given a shortcode name, will instantiate the shortcode and call it's run() method
339
+	 *
340
+	 * @param string $shortcode_class
341
+	 * @param WP     $wp
342
+	 * @throws ReflectionException
343
+	 */
344
+	public function initializeShortcode($shortcode_class = '', WP $wp = null)
345
+	{
346
+		// don't do anything if shortcode is already initialized
347
+		if (
348
+			empty($this->registry->shortcodes->{$shortcode_class})
349
+			|| ! is_string($this->registry->shortcodes->{$shortcode_class})
350
+		) {
351
+			return;
352
+		}
353
+		// let's pause to reflect on this...
354
+		$sc_reflector = new ReflectionClass(LegacyShortcodesManager::addShortcodeClassPrefix($shortcode_class));
355
+		// ensure that class is actually a shortcode
356
+		if (
357
+			defined('WP_DEBUG')
358
+			&& WP_DEBUG === true
359
+			&& ! $sc_reflector->isSubclassOf('EES_Shortcode')
360
+		) {
361
+			EE_Error::add_error(
362
+				sprintf(
363
+					esc_html__(
364
+						'The requested %s shortcode is not of the class "EES_Shortcode". Please check your files.',
365
+						'event_espresso'
366
+					),
367
+					$shortcode_class
368
+				),
369
+				__FILE__,
370
+				__FUNCTION__,
371
+				__LINE__
372
+			);
373
+			add_filter('FHEE_run_EE_the_content', '__return_true');
374
+			return;
375
+		}
376
+		global $wp;
377
+		// and pass the request object to the run method
378
+		$this->registry->shortcodes->{$shortcode_class} = $sc_reflector->newInstance();
379
+		// fire the shortcode class's run method, so that it can activate resources
380
+		$this->registry->shortcodes->{$shortcode_class}->run($wp);
381
+	}
382
+
383
+
384
+	/**
385
+	 * get classname, remove EES_prefix, and convert to UPPERCASE
386
+	 *
387
+	 * @param string $class_name
388
+	 * @return string
389
+	 */
390
+	public static function generateShortcodeTagFromClassName($class_name)
391
+	{
392
+		return strtoupper(str_replace('EES_', '', $class_name));
393
+	}
394
+
395
+
396
+	/**
397
+	 * add EES_prefix and Capitalize words
398
+	 *
399
+	 * @param string $tag
400
+	 * @return string
401
+	 */
402
+	public static function generateShortcodeClassNameFromTag($tag)
403
+	{
404
+		// order of operation runs from inside to out
405
+		// 5) maybe add prefix
406
+		return LegacyShortcodesManager::addShortcodeClassPrefix(
407
+			// 4) find spaces, replace with underscores
408
+			str_replace(
409
+				' ',
410
+				'_',
411
+				// 3) capitalize first letter of each word
412
+				ucwords(
413
+					// 2) also change to lowercase so ucwords() will work
414
+					strtolower(
415
+						// 1) find underscores, replace with spaces so ucwords() will work
416
+						str_replace(
417
+							'_',
418
+							' ',
419
+							$tag
420
+						)
421
+					)
422
+				)
423
+			)
424
+		);
425
+	}
426
+
427
+
428
+	/**
429
+	 * maybe add EES_prefix
430
+	 *
431
+	 * @param string $class_name
432
+	 * @return string
433
+	 */
434
+	public static function addShortcodeClassPrefix($class_name)
435
+	{
436
+		return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
437
+	}
438
+
439
+
440
+	/**
441
+	 * @return array
442
+	 */
443
+	public function getEspressoShortcodeTags()
444
+	{
445
+		static $shortcode_tags = array();
446
+		if (empty($shortcode_tags)) {
447
+			$shortcode_tags = array_keys((array) $this->registry->shortcodes);
448
+		}
449
+		return $shortcode_tags;
450
+	}
451
+
452
+
453
+	/**
454
+	 * @param string $content
455
+	 * @return string
456
+	 * @throws ReflectionException
457
+	 */
458
+	public function doShortcode($content)
459
+	{
460
+		foreach ($this->getEspressoShortcodeTags() as $shortcode_tag) {
461
+			if (strpos($content, $shortcode_tag) !== false) {
462
+				$shortcode_class = LegacyShortcodesManager::generateShortcodeClassNameFromTag($shortcode_tag);
463
+				$this->initializeShortcode($shortcode_class);
464
+			}
465
+		}
466
+		return do_shortcode($content);
467
+	}
468 468
 }
Please login to merge, or discard this patch.
core/services/assets/Registry.php 2 patches
Indentation   +570 added lines, -570 removed lines patch added patch discarded remove patch
@@ -25,581 +25,581 @@
 block discarded – undo
25 25
 class Registry
26 26
 {
27 27
 
28
-    const FILE_NAME_BUILD_MANIFEST = 'build-manifest.json';
29
-
30
-    /**
31
-     * @var AssetCollection[] $assets
32
-     */
33
-    protected $assets = [];
34
-
35
-    /**
36
-     * @var AssetManifestInterface
37
-     */
38
-    private $asset_manifest;
39
-
40
-    /**
41
-     * This holds the js_data data object that will be exposed on pages that enqueue the `eejs-core` script.
42
-     *
43
-     * @var array
44
-     */
45
-    protected $js_data = [];
46
-
47
-    /**
48
-     * This keeps track of all scripts with registered data.  It is used to prevent duplicate data objects setup in the
49
-     * page source.
50
-     *
51
-     * @var array
52
-     */
53
-    private $script_handles_with_data = [];
54
-
55
-
56
-    /**
57
-     * Registry constructor.
58
-     * Hooking into WP actions for script registry.
59
-     *
60
-     * @param AssetCollection        $assets
61
-     * @param AssetManifestInterface $asset_manifest
62
-     * @throws InvalidArgumentException
63
-     * @throws InvalidDataTypeException
64
-     * @throws InvalidInterfaceException
65
-     */
66
-    public function __construct(AssetCollection $assets, AssetManifestInterface $asset_manifest)
67
-    {
68
-        $this->addAssetCollection($assets);
69
-        $this->asset_manifest = $asset_manifest;
70
-        $this->asset_manifest->initialize();
71
-        add_action('wp_enqueue_scripts', array($this, 'registerScriptsAndStyles'), 4);
72
-        add_action('admin_enqueue_scripts', array($this, 'registerScriptsAndStyles'), 4);
73
-        add_action('wp_enqueue_scripts', array($this, 'enqueueData'), 5);
74
-        add_action('admin_enqueue_scripts', array($this, 'enqueueData'), 5);
75
-        add_action('wp_print_footer_scripts', array($this, 'enqueueData'), 1);
76
-        add_action('admin_print_footer_scripts', array($this, 'enqueueData'), 1);
77
-    }
78
-
79
-
80
-    /**
81
-     * @param AssetCollection $asset_collection
82
-     */
83
-    public function addAssetCollection(AssetCollection $asset_collection)
84
-    {
85
-        $id = $asset_collection->collectionIdentifier();
86
-        if (! array_key_exists($id, $this->assets)) {
87
-            $this->assets[ $id ] = $asset_collection;
88
-        }
89
-    }
90
-
91
-
92
-
93
-    /**
94
-     * Callback for the wp_enqueue_scripts actions used to register assets.
95
-     *
96
-     * @throws Exception
97
-     * @since 4.9.62.p
98
-     */
99
-    public function registerScriptsAndStyles()
100
-    {
101
-        try {
102
-            foreach ($this->assets as $asset_collection) {
103
-                $this->registerScripts($asset_collection->getJavascriptAssets());
104
-                $this->registerStyles($asset_collection->getStylesheetAssets());
105
-            }
106
-        } catch (Exception $exception) {
107
-            new ExceptionStackTraceDisplay($exception);
108
-        }
109
-    }
110
-
111
-
112
-    /**
113
-     * Registers JS assets with WP core
114
-     *
115
-     * @param JavascriptAsset[] $scripts
116
-     * @throws AssetRegistrationException
117
-     * @throws InvalidDataTypeException
118
-     * @throws DomainException
119
-     * @since 4.9.62.p
120
-     */
121
-    public function registerScripts(array $scripts)
122
-    {
123
-        foreach ($scripts as $script) {
124
-            // skip to next script if this has already been done
125
-            if ($script->isRegistered()) {
126
-                continue;
127
-            }
128
-            do_action(
129
-                'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__before_script',
130
-                $script
131
-            );
132
-            $registered = wp_register_script(
133
-                $script->handle(),
134
-                $script->source(),
135
-                $script->dependencies(),
136
-                $script->version(),
137
-                $script->loadInFooter()
138
-            );
139
-            if (! $registered && $this->debug()) {
140
-                throw new AssetRegistrationException($script->handle());
141
-            }
142
-            $script->setRegistered($registered);
143
-            if ($script->enqueueImmediately()) {
144
-                wp_enqueue_script($script->handle());
145
-            }
146
-            do_action(
147
-                'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__after_script',
148
-                $script
149
-            );
150
-        }
151
-    }
152
-
153
-
154
-    /**
155
-     * Registers CSS assets with WP core
156
-     *
157
-     * @param StylesheetAsset[] $styles
158
-     * @throws InvalidDataTypeException
159
-     * @throws DomainException
160
-     * @since 4.9.62.p
161
-     */
162
-    public function registerStyles(array $styles)
163
-    {
164
-        foreach ($styles as $style) {
165
-            // skip to next style if this has already been done
166
-            if ($style->isRegistered()) {
167
-                continue;
168
-            }
169
-            do_action(
170
-                'AHEE__EventEspresso_core_services_assets_Registry__registerStyles__before_style',
171
-                $style
172
-            );
173
-            wp_register_style(
174
-                $style->handle(),
175
-                $style->source(),
176
-                $style->dependencies(),
177
-                $style->version(),
178
-                $style->media()
179
-            );
180
-            $style->setRegistered();
181
-            if ($style->enqueueImmediately()) {
182
-                wp_enqueue_style($style->handle());
183
-            }
184
-            do_action(
185
-                'AHEE__EventEspresso_core_services_assets_Registry__registerStyles__after_style',
186
-                $style
187
-            );
188
-        }
189
-    }
190
-
191
-
192
-    /**
193
-     * Call back for the script print in frontend and backend.
194
-     * Used to call wp_localize_scripts so that data can be added throughout the runtime until this later hook point.
195
-     *
196
-     * @throws Exception
197
-     * @since 4.9.31.rc.015
198
-     */
199
-    public function enqueueData()
200
-    {
201
-        try {
202
-            $this->removeAlreadyRegisteredDataForScriptHandles();
203
-            wp_add_inline_script(
204
-                CoreAssetManager::JS_HANDLE_JS_CORE,
205
-                'var eejsdata=' . wp_json_encode(['data' => $this->js_data]),
206
-                'before'
207
-            );
208
-            foreach ($this->assets as $asset_collection) {
209
-                $scripts = $asset_collection->getJavascriptAssetsWithData();
210
-                foreach ($scripts as $script) {
211
-                    $this->addRegisteredScriptHandlesWithData($script->handle());
212
-                    if ($script->hasInlineDataCallback()) {
213
-                        $localize = $script->inlineDataCallback();
214
-                        $localize();
215
-                    }
216
-                }
217
-            }
218
-        } catch (Exception $exception) {
219
-            EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
220
-            new ExceptionStackTraceDisplay($exception);
221
-        }
222
-    }
223
-
224
-
225
-    /**
226
-     * Used to add data to eejs.data object.
227
-     * Note:  Overriding existing data is not allowed.
228
-     * Data will be accessible as a javascript object when you list `eejs-core` as a dependency for your javascript.
229
-     * If the data you add is something like this:
230
-     *  $this->addData( 'my_plugin_data', array( 'foo' => 'gar' ) );
231
-     * It will be exposed in the page source as:
232
-     *  eejs.data.my_plugin_data.foo == gar
233
-     *
234
-     * @param string       $key   Key used to access your data
235
-     * @param string|array $value Value to attach to key
236
-     * @throws InvalidArgumentException
237
-     */
238
-    public function addData(string $key, $value)
239
-    {
240
-        if ($this->verifyDataNotExisting($key)) {
241
-            $this->js_data[ $key ] = $value;
242
-        }
243
-    }
244
-
245
-
246
-    /**
247
-     * Similar to addData except this allows for users to push values to an existing key where the values on key are
248
-     * elements in an array.
249
-     *
250
-     * When you use this method, the value you include will be merged with the array on $key.
251
-     * So if the $key was 'test' and you added a value of ['my_data'] then it would be represented in the javascript
252
-     * object like this, eejs.data.test = [ my_data,
253
-     * ]
254
-     * If there has already been a scalar value attached to the data object given key (via addData for instance), then
255
-     * this will throw an exception.
256
-     *
257
-     * Caution: Only add data using this method if you are okay with the potential for additional data added on the same
258
-     * key potentially overriding the existing data on merge (specifically with associative arrays).
259
-     *
260
-     * @param string       $key   Key to attach data to.
261
-     * @param string|array $value Value being registered.
262
-     * @throws InvalidArgumentException
263
-     */
264
-    public function pushData(string $key, $value)
265
-    {
266
-        if (
267
-            isset($this->js_data[ $key ])
268
-            && ! is_array($this->js_data[ $key ])
269
-        ) {
270
-            if (! $this->debug()) {
271
-                return;
272
-            }
273
-            throw new InvalidArgumentException(
274
-                sprintf(
275
-                    esc_html__(
276
-                        'The value for %1$s is already set and it is not an array. The %2$s method can only be used to
28
+	const FILE_NAME_BUILD_MANIFEST = 'build-manifest.json';
29
+
30
+	/**
31
+	 * @var AssetCollection[] $assets
32
+	 */
33
+	protected $assets = [];
34
+
35
+	/**
36
+	 * @var AssetManifestInterface
37
+	 */
38
+	private $asset_manifest;
39
+
40
+	/**
41
+	 * This holds the js_data data object that will be exposed on pages that enqueue the `eejs-core` script.
42
+	 *
43
+	 * @var array
44
+	 */
45
+	protected $js_data = [];
46
+
47
+	/**
48
+	 * This keeps track of all scripts with registered data.  It is used to prevent duplicate data objects setup in the
49
+	 * page source.
50
+	 *
51
+	 * @var array
52
+	 */
53
+	private $script_handles_with_data = [];
54
+
55
+
56
+	/**
57
+	 * Registry constructor.
58
+	 * Hooking into WP actions for script registry.
59
+	 *
60
+	 * @param AssetCollection        $assets
61
+	 * @param AssetManifestInterface $asset_manifest
62
+	 * @throws InvalidArgumentException
63
+	 * @throws InvalidDataTypeException
64
+	 * @throws InvalidInterfaceException
65
+	 */
66
+	public function __construct(AssetCollection $assets, AssetManifestInterface $asset_manifest)
67
+	{
68
+		$this->addAssetCollection($assets);
69
+		$this->asset_manifest = $asset_manifest;
70
+		$this->asset_manifest->initialize();
71
+		add_action('wp_enqueue_scripts', array($this, 'registerScriptsAndStyles'), 4);
72
+		add_action('admin_enqueue_scripts', array($this, 'registerScriptsAndStyles'), 4);
73
+		add_action('wp_enqueue_scripts', array($this, 'enqueueData'), 5);
74
+		add_action('admin_enqueue_scripts', array($this, 'enqueueData'), 5);
75
+		add_action('wp_print_footer_scripts', array($this, 'enqueueData'), 1);
76
+		add_action('admin_print_footer_scripts', array($this, 'enqueueData'), 1);
77
+	}
78
+
79
+
80
+	/**
81
+	 * @param AssetCollection $asset_collection
82
+	 */
83
+	public function addAssetCollection(AssetCollection $asset_collection)
84
+	{
85
+		$id = $asset_collection->collectionIdentifier();
86
+		if (! array_key_exists($id, $this->assets)) {
87
+			$this->assets[ $id ] = $asset_collection;
88
+		}
89
+	}
90
+
91
+
92
+
93
+	/**
94
+	 * Callback for the wp_enqueue_scripts actions used to register assets.
95
+	 *
96
+	 * @throws Exception
97
+	 * @since 4.9.62.p
98
+	 */
99
+	public function registerScriptsAndStyles()
100
+	{
101
+		try {
102
+			foreach ($this->assets as $asset_collection) {
103
+				$this->registerScripts($asset_collection->getJavascriptAssets());
104
+				$this->registerStyles($asset_collection->getStylesheetAssets());
105
+			}
106
+		} catch (Exception $exception) {
107
+			new ExceptionStackTraceDisplay($exception);
108
+		}
109
+	}
110
+
111
+
112
+	/**
113
+	 * Registers JS assets with WP core
114
+	 *
115
+	 * @param JavascriptAsset[] $scripts
116
+	 * @throws AssetRegistrationException
117
+	 * @throws InvalidDataTypeException
118
+	 * @throws DomainException
119
+	 * @since 4.9.62.p
120
+	 */
121
+	public function registerScripts(array $scripts)
122
+	{
123
+		foreach ($scripts as $script) {
124
+			// skip to next script if this has already been done
125
+			if ($script->isRegistered()) {
126
+				continue;
127
+			}
128
+			do_action(
129
+				'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__before_script',
130
+				$script
131
+			);
132
+			$registered = wp_register_script(
133
+				$script->handle(),
134
+				$script->source(),
135
+				$script->dependencies(),
136
+				$script->version(),
137
+				$script->loadInFooter()
138
+			);
139
+			if (! $registered && $this->debug()) {
140
+				throw new AssetRegistrationException($script->handle());
141
+			}
142
+			$script->setRegistered($registered);
143
+			if ($script->enqueueImmediately()) {
144
+				wp_enqueue_script($script->handle());
145
+			}
146
+			do_action(
147
+				'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__after_script',
148
+				$script
149
+			);
150
+		}
151
+	}
152
+
153
+
154
+	/**
155
+	 * Registers CSS assets with WP core
156
+	 *
157
+	 * @param StylesheetAsset[] $styles
158
+	 * @throws InvalidDataTypeException
159
+	 * @throws DomainException
160
+	 * @since 4.9.62.p
161
+	 */
162
+	public function registerStyles(array $styles)
163
+	{
164
+		foreach ($styles as $style) {
165
+			// skip to next style if this has already been done
166
+			if ($style->isRegistered()) {
167
+				continue;
168
+			}
169
+			do_action(
170
+				'AHEE__EventEspresso_core_services_assets_Registry__registerStyles__before_style',
171
+				$style
172
+			);
173
+			wp_register_style(
174
+				$style->handle(),
175
+				$style->source(),
176
+				$style->dependencies(),
177
+				$style->version(),
178
+				$style->media()
179
+			);
180
+			$style->setRegistered();
181
+			if ($style->enqueueImmediately()) {
182
+				wp_enqueue_style($style->handle());
183
+			}
184
+			do_action(
185
+				'AHEE__EventEspresso_core_services_assets_Registry__registerStyles__after_style',
186
+				$style
187
+			);
188
+		}
189
+	}
190
+
191
+
192
+	/**
193
+	 * Call back for the script print in frontend and backend.
194
+	 * Used to call wp_localize_scripts so that data can be added throughout the runtime until this later hook point.
195
+	 *
196
+	 * @throws Exception
197
+	 * @since 4.9.31.rc.015
198
+	 */
199
+	public function enqueueData()
200
+	{
201
+		try {
202
+			$this->removeAlreadyRegisteredDataForScriptHandles();
203
+			wp_add_inline_script(
204
+				CoreAssetManager::JS_HANDLE_JS_CORE,
205
+				'var eejsdata=' . wp_json_encode(['data' => $this->js_data]),
206
+				'before'
207
+			);
208
+			foreach ($this->assets as $asset_collection) {
209
+				$scripts = $asset_collection->getJavascriptAssetsWithData();
210
+				foreach ($scripts as $script) {
211
+					$this->addRegisteredScriptHandlesWithData($script->handle());
212
+					if ($script->hasInlineDataCallback()) {
213
+						$localize = $script->inlineDataCallback();
214
+						$localize();
215
+					}
216
+				}
217
+			}
218
+		} catch (Exception $exception) {
219
+			EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
220
+			new ExceptionStackTraceDisplay($exception);
221
+		}
222
+	}
223
+
224
+
225
+	/**
226
+	 * Used to add data to eejs.data object.
227
+	 * Note:  Overriding existing data is not allowed.
228
+	 * Data will be accessible as a javascript object when you list `eejs-core` as a dependency for your javascript.
229
+	 * If the data you add is something like this:
230
+	 *  $this->addData( 'my_plugin_data', array( 'foo' => 'gar' ) );
231
+	 * It will be exposed in the page source as:
232
+	 *  eejs.data.my_plugin_data.foo == gar
233
+	 *
234
+	 * @param string       $key   Key used to access your data
235
+	 * @param string|array $value Value to attach to key
236
+	 * @throws InvalidArgumentException
237
+	 */
238
+	public function addData(string $key, $value)
239
+	{
240
+		if ($this->verifyDataNotExisting($key)) {
241
+			$this->js_data[ $key ] = $value;
242
+		}
243
+	}
244
+
245
+
246
+	/**
247
+	 * Similar to addData except this allows for users to push values to an existing key where the values on key are
248
+	 * elements in an array.
249
+	 *
250
+	 * When you use this method, the value you include will be merged with the array on $key.
251
+	 * So if the $key was 'test' and you added a value of ['my_data'] then it would be represented in the javascript
252
+	 * object like this, eejs.data.test = [ my_data,
253
+	 * ]
254
+	 * If there has already been a scalar value attached to the data object given key (via addData for instance), then
255
+	 * this will throw an exception.
256
+	 *
257
+	 * Caution: Only add data using this method if you are okay with the potential for additional data added on the same
258
+	 * key potentially overriding the existing data on merge (specifically with associative arrays).
259
+	 *
260
+	 * @param string       $key   Key to attach data to.
261
+	 * @param string|array $value Value being registered.
262
+	 * @throws InvalidArgumentException
263
+	 */
264
+	public function pushData(string $key, $value)
265
+	{
266
+		if (
267
+			isset($this->js_data[ $key ])
268
+			&& ! is_array($this->js_data[ $key ])
269
+		) {
270
+			if (! $this->debug()) {
271
+				return;
272
+			}
273
+			throw new InvalidArgumentException(
274
+				sprintf(
275
+					esc_html__(
276
+						'The value for %1$s is already set and it is not an array. The %2$s method can only be used to
277 277
                          push values to this data element when it is an array.',
278
-                        'event_espresso'
279
-                    ),
280
-                    $key,
281
-                    __METHOD__
282
-                )
283
-            );
284
-        }
285
-        if (! isset($this->js_data[ $key ])) {
286
-            $this->js_data[ $key ] = is_array($value) ? $value : [$value];
287
-        } else {
288
-            $this->js_data[ $key ] = array_merge($this->js_data[ $key ], (array) $value);
289
-        }
290
-    }
291
-
292
-
293
-    /**
294
-     * Used to set content used by javascript for a template.
295
-     * Note: Overrides of existing registered templates are not allowed.
296
-     *
297
-     * @param string $template_reference
298
-     * @param string $template_content
299
-     * @throws InvalidArgumentException
300
-     */
301
-    public function addTemplate(string $template_reference, string $template_content)
302
-    {
303
-        if (! isset($this->js_data['templates'])) {
304
-            $this->js_data['templates'] = [];
305
-        }
306
-        //no overrides allowed.
307
-        if (isset($this->js_data['templates'][ $template_reference ])) {
308
-            if (! $this->debug()) {
309
-                return;
310
-            }
311
-            throw new InvalidArgumentException(
312
-                sprintf(
313
-                    esc_html__(
314
-                        'The %1$s key already exists for the templates array in the js data array.  No overrides are allowed.',
315
-                        'event_espresso'
316
-                    ),
317
-                    $template_reference
318
-                )
319
-            );
320
-        }
321
-        $this->js_data['templates'][ $template_reference ] = $template_content;
322
-    }
323
-
324
-
325
-    /**
326
-     * Retrieve the template content already registered for the given reference.
327
-     *
328
-     * @param string $template_reference
329
-     * @return string
330
-     */
331
-    public function getTemplate(string $template_reference): string
332
-    {
333
-        return $this->js_data['templates'][ $template_reference ] ?? '';
334
-    }
335
-
336
-
337
-    /**
338
-     * Retrieve registered data.
339
-     *
340
-     * @param string $key Name of key to attach data to.
341
-     * @return mixed                If there is no for the given key, then false is returned.
342
-     */
343
-    public function getData(string $key)
344
-    {
345
-        return array_key_exists($key, $this->js_data) ? $this->js_data[ $key ] : null;
346
-    }
347
-
348
-
349
-    /**
350
-     * Verifies whether the given data exists already on the js_data array.
351
-     * Overriding data is not allowed.
352
-     *
353
-     * @param string $key Index for data.
354
-     * @return bool        If valid then return true.
355
-     * @throws InvalidArgumentException if data already exists.
356
-     */
357
-    protected function verifyDataNotExisting(string $key): bool
358
-    {
359
-        if (isset($this->js_data[ $key ])) {
360
-            if (! $this->debug()) {
361
-                return false;
362
-            }
363
-            if (is_array($this->js_data[ $key ])) {
364
-                throw new InvalidArgumentException(
365
-                    sprintf(
366
-                        esc_html__(
367
-                            'The value for %1$s already exists in the Registry::eejs object.
278
+						'event_espresso'
279
+					),
280
+					$key,
281
+					__METHOD__
282
+				)
283
+			);
284
+		}
285
+		if (! isset($this->js_data[ $key ])) {
286
+			$this->js_data[ $key ] = is_array($value) ? $value : [$value];
287
+		} else {
288
+			$this->js_data[ $key ] = array_merge($this->js_data[ $key ], (array) $value);
289
+		}
290
+	}
291
+
292
+
293
+	/**
294
+	 * Used to set content used by javascript for a template.
295
+	 * Note: Overrides of existing registered templates are not allowed.
296
+	 *
297
+	 * @param string $template_reference
298
+	 * @param string $template_content
299
+	 * @throws InvalidArgumentException
300
+	 */
301
+	public function addTemplate(string $template_reference, string $template_content)
302
+	{
303
+		if (! isset($this->js_data['templates'])) {
304
+			$this->js_data['templates'] = [];
305
+		}
306
+		//no overrides allowed.
307
+		if (isset($this->js_data['templates'][ $template_reference ])) {
308
+			if (! $this->debug()) {
309
+				return;
310
+			}
311
+			throw new InvalidArgumentException(
312
+				sprintf(
313
+					esc_html__(
314
+						'The %1$s key already exists for the templates array in the js data array.  No overrides are allowed.',
315
+						'event_espresso'
316
+					),
317
+					$template_reference
318
+				)
319
+			);
320
+		}
321
+		$this->js_data['templates'][ $template_reference ] = $template_content;
322
+	}
323
+
324
+
325
+	/**
326
+	 * Retrieve the template content already registered for the given reference.
327
+	 *
328
+	 * @param string $template_reference
329
+	 * @return string
330
+	 */
331
+	public function getTemplate(string $template_reference): string
332
+	{
333
+		return $this->js_data['templates'][ $template_reference ] ?? '';
334
+	}
335
+
336
+
337
+	/**
338
+	 * Retrieve registered data.
339
+	 *
340
+	 * @param string $key Name of key to attach data to.
341
+	 * @return mixed                If there is no for the given key, then false is returned.
342
+	 */
343
+	public function getData(string $key)
344
+	{
345
+		return array_key_exists($key, $this->js_data) ? $this->js_data[ $key ] : null;
346
+	}
347
+
348
+
349
+	/**
350
+	 * Verifies whether the given data exists already on the js_data array.
351
+	 * Overriding data is not allowed.
352
+	 *
353
+	 * @param string $key Index for data.
354
+	 * @return bool        If valid then return true.
355
+	 * @throws InvalidArgumentException if data already exists.
356
+	 */
357
+	protected function verifyDataNotExisting(string $key): bool
358
+	{
359
+		if (isset($this->js_data[ $key ])) {
360
+			if (! $this->debug()) {
361
+				return false;
362
+			}
363
+			if (is_array($this->js_data[ $key ])) {
364
+				throw new InvalidArgumentException(
365
+					sprintf(
366
+						esc_html__(
367
+							'The value for %1$s already exists in the Registry::eejs object.
368 368
                             Overrides are not allowed. Since the value of this data is an array, you may want to use the
369 369
                             %2$s method to push your value to the array.',
370
-                            'event_espresso'
371
-                        ),
372
-                        $key,
373
-                        'pushData()'
374
-                    )
375
-                );
376
-            }
377
-            throw new InvalidArgumentException(
378
-                sprintf(
379
-                    esc_html__(
380
-                        'The value for %1$s already exists in the Registry::eejs object. Overrides are not
370
+							'event_espresso'
371
+						),
372
+						$key,
373
+						'pushData()'
374
+					)
375
+				);
376
+			}
377
+			throw new InvalidArgumentException(
378
+				sprintf(
379
+					esc_html__(
380
+						'The value for %1$s already exists in the Registry::eejs object. Overrides are not
381 381
                         allowed.  Consider attaching your value to a different key',
382
-                        'event_espresso'
383
-                    ),
384
-                    $key
385
-                )
386
-            );
387
-        }
388
-        return true;
389
-    }
390
-
391
-
392
-    /**
393
-     * Get the actual asset path for asset manifests.
394
-     * If there is no asset path found for the given $chunk_name, then the $chunk_name is returned.
395
-     *
396
-     * @param string $namespace  The namespace associated with the manifest file hosting the map of chunk_name to actual
397
-     *                           asset file location.
398
-     * @param string $chunk_name
399
-     * @param string $asset_type
400
-     * @return string
401
-     * @since 4.9.59.p
402
-     */
403
-    public function getAssetUrl(string $namespace, string $chunk_name, string $asset_type): string
404
-    {
405
-        return apply_filters(
406
-            'FHEE__EventEspresso_core_services_assets_Registry__getAssetUrl',
407
-            $this->asset_manifest->getAssetUrl($chunk_name, $asset_type),
408
-            $namespace,
409
-            $chunk_name,
410
-            $asset_type
411
-        );
412
-    }
413
-
414
-
415
-    /**
416
-     * Return the url to a js file for the given namespace and chunk name.
417
-     *
418
-     * @param string $namespace
419
-     * @param string $chunk_name
420
-     * @return string
421
-     */
422
-    public function getJsUrl(string $namespace, string $chunk_name): string
423
-    {
424
-        return $this->getAssetUrl($namespace, $chunk_name, Asset::TYPE_JS);
425
-    }
426
-
427
-
428
-    /**
429
-     * Return the url to a css file for the given namespace and chunk name.
430
-     *
431
-     * @param string $namespace
432
-     * @param string $chunk_name
433
-     * @return string
434
-     */
435
-    public function getCssUrl(string $namespace, string $chunk_name): string
436
-    {
437
-        return $this->getAssetUrl($namespace, $chunk_name, Asset::TYPE_CSS);
438
-    }
439
-
440
-
441
-    /**
442
-     * This is used to set registered script handles that have data.
443
-     *
444
-     * @param string $script_handle
445
-     */
446
-    private function addRegisteredScriptHandlesWithData(string $script_handle)
447
-    {
448
-        $this->script_handles_with_data[ $script_handle ] = $script_handle;
449
-    }
450
-
451
-
452
-    /**i
382
+						'event_espresso'
383
+					),
384
+					$key
385
+				)
386
+			);
387
+		}
388
+		return true;
389
+	}
390
+
391
+
392
+	/**
393
+	 * Get the actual asset path for asset manifests.
394
+	 * If there is no asset path found for the given $chunk_name, then the $chunk_name is returned.
395
+	 *
396
+	 * @param string $namespace  The namespace associated with the manifest file hosting the map of chunk_name to actual
397
+	 *                           asset file location.
398
+	 * @param string $chunk_name
399
+	 * @param string $asset_type
400
+	 * @return string
401
+	 * @since 4.9.59.p
402
+	 */
403
+	public function getAssetUrl(string $namespace, string $chunk_name, string $asset_type): string
404
+	{
405
+		return apply_filters(
406
+			'FHEE__EventEspresso_core_services_assets_Registry__getAssetUrl',
407
+			$this->asset_manifest->getAssetUrl($chunk_name, $asset_type),
408
+			$namespace,
409
+			$chunk_name,
410
+			$asset_type
411
+		);
412
+	}
413
+
414
+
415
+	/**
416
+	 * Return the url to a js file for the given namespace and chunk name.
417
+	 *
418
+	 * @param string $namespace
419
+	 * @param string $chunk_name
420
+	 * @return string
421
+	 */
422
+	public function getJsUrl(string $namespace, string $chunk_name): string
423
+	{
424
+		return $this->getAssetUrl($namespace, $chunk_name, Asset::TYPE_JS);
425
+	}
426
+
427
+
428
+	/**
429
+	 * Return the url to a css file for the given namespace and chunk name.
430
+	 *
431
+	 * @param string $namespace
432
+	 * @param string $chunk_name
433
+	 * @return string
434
+	 */
435
+	public function getCssUrl(string $namespace, string $chunk_name): string
436
+	{
437
+		return $this->getAssetUrl($namespace, $chunk_name, Asset::TYPE_CSS);
438
+	}
439
+
440
+
441
+	/**
442
+	 * This is used to set registered script handles that have data.
443
+	 *
444
+	 * @param string $script_handle
445
+	 */
446
+	private function addRegisteredScriptHandlesWithData(string $script_handle)
447
+	{
448
+		$this->script_handles_with_data[ $script_handle ] = $script_handle;
449
+	}
450
+
451
+
452
+	/**i
453 453
      * Checks WP_Scripts for all of each script handle registered internally as having data and unsets from the
454 454
      * Dependency stored in WP_Scripts if its set.
455 455
      */
456
-    private function removeAlreadyRegisteredDataForScriptHandles()
457
-    {
458
-        if (empty($this->script_handles_with_data)) {
459
-            return;
460
-        }
461
-        foreach ($this->script_handles_with_data as $script_handle) {
462
-            $this->removeAlreadyRegisteredDataForScriptHandle($script_handle);
463
-        }
464
-    }
465
-
466
-
467
-    /**
468
-     * Removes any data dependency registered in WP_Scripts if its set.
469
-     *
470
-     * @param string $script_handle
471
-     */
472
-    private function removeAlreadyRegisteredDataForScriptHandle(string $script_handle)
473
-    {
474
-        if (isset($this->script_handles_with_data[ $script_handle ])) {
475
-            global $wp_scripts;
476
-            $unset_handle = false;
477
-            if ($wp_scripts->get_data($script_handle, 'data')) {
478
-                unset($wp_scripts->registered[ $script_handle ]->extra['data']);
479
-                $unset_handle = true;
480
-            }
481
-            //deal with inline_scripts
482
-            if ($wp_scripts->get_data($script_handle, 'before')) {
483
-                unset($wp_scripts->registered[ $script_handle ]->extra['before']);
484
-                $unset_handle = true;
485
-            }
486
-            if ($wp_scripts->get_data($script_handle, 'after')) {
487
-                unset($wp_scripts->registered[ $script_handle ]->extra['after']);
488
-            }
489
-            if ($unset_handle) {
490
-                unset($this->script_handles_with_data[ $script_handle ]);
491
-            }
492
-        }
493
-    }
494
-
495
-
496
-    /**
497
-     * @since 4.9.63.p
498
-     * @return bool
499
-     * @since 4.9.63.p
500
-     */
501
-    private function debug(): bool
502
-    {
503
-        return apply_filters(
504
-            'FHEE__EventEspresso_core_services_assets_Registry__debug',
505
-            defined('EE_DEBUG') && EE_DEBUG
506
-        );
507
-    }
508
-
509
-
510
-    /**************** deprecated ****************/
511
-
512
-
513
-
514
-    /**
515
-     * @return null
516
-     * @deprecated $VID:$
517
-     */
518
-    public function getI18nRegistry()
519
-    {
520
-        return null;
521
-    }
522
-
523
-
524
-    /**
525
-     * @param string $handle
526
-     * @deprecated $VID:$
527
-     */
528
-    public function registerTranslation($handle)
529
-    {
530
-    }
531
-
532
-
533
-    /**
534
-     * @param string $namespace
535
-     * @param string $chunk_name
536
-     * @return array
537
-     * @deprecated $VID:$
538
-     */
539
-    public function getCssAssetDetails($namespace, $chunk_name)
540
-    {
541
-        return [
542
-            AssetManifest::KEY_DEPENDENCIES => $this->asset_manifest->getAssetDependencies($chunk_name, Asset::TYPE_CSS),
543
-            AssetManifest::KEY_VERSION => $this->asset_manifest->getAssetVersion($chunk_name, Asset::TYPE_CSS),
544
-        ];
545
-    }
546
-
547
-
548
-    /**
549
-     * @param string $namespace
550
-     * @param string $chunk_name
551
-     * @return array
552
-     * @deprecated $VID:$
553
-     */
554
-    public function getCssDependencies($namespace, $chunk_name)
555
-    {
556
-        return $this->asset_manifest->getAssetDependencies($chunk_name, AssetManifest::ASSET_EXT_CSS);
557
-    }
558
-
559
-
560
-    /**
561
-     * @param string $namespace
562
-     * @param string $chunk_name
563
-     * @return array
564
-     * @deprecated $VID:$
565
-     */
566
-    public function getJsAssetDetails($namespace, $chunk_name)
567
-    {
568
-        return [
569
-            AssetManifest::KEY_DEPENDENCIES => $this->asset_manifest->getAssetDependencies($chunk_name, Asset::TYPE_JS),
570
-            AssetManifest::KEY_VERSION => $this->asset_manifest->getAssetVersion($chunk_name, Asset::TYPE_JS),
571
-        ];
572
-    }
573
-
574
-
575
-    /**
576
-     * @param string $namespace
577
-     * @param string $chunk_name
578
-     * @return array
579
-     * @deprecated $VID:$
580
-     */
581
-    public function getJsDependencies($namespace, $chunk_name)
582
-    {
583
-        return $this->asset_manifest->getAssetDependencies($chunk_name);
584
-    }
585
-
586
-
587
-    /**
588
-     * @deprecated $VID:$
589
-     */
590
-    public function registerManifestFiles()
591
-    {
592
-    }
593
-
594
-
595
-    /**
596
-     * @param string $namespace
597
-     * @param string $url_base
598
-     * @param string $manifest_file
599
-     * @param string $manifest_file_path
600
-     * @deprecated $VID:$
601
-     */
602
-    public function registerManifestFile($namespace, $url_base, $manifest_file, $manifest_file_path = '')
603
-    {
604
-    }
456
+	private function removeAlreadyRegisteredDataForScriptHandles()
457
+	{
458
+		if (empty($this->script_handles_with_data)) {
459
+			return;
460
+		}
461
+		foreach ($this->script_handles_with_data as $script_handle) {
462
+			$this->removeAlreadyRegisteredDataForScriptHandle($script_handle);
463
+		}
464
+	}
465
+
466
+
467
+	/**
468
+	 * Removes any data dependency registered in WP_Scripts if its set.
469
+	 *
470
+	 * @param string $script_handle
471
+	 */
472
+	private function removeAlreadyRegisteredDataForScriptHandle(string $script_handle)
473
+	{
474
+		if (isset($this->script_handles_with_data[ $script_handle ])) {
475
+			global $wp_scripts;
476
+			$unset_handle = false;
477
+			if ($wp_scripts->get_data($script_handle, 'data')) {
478
+				unset($wp_scripts->registered[ $script_handle ]->extra['data']);
479
+				$unset_handle = true;
480
+			}
481
+			//deal with inline_scripts
482
+			if ($wp_scripts->get_data($script_handle, 'before')) {
483
+				unset($wp_scripts->registered[ $script_handle ]->extra['before']);
484
+				$unset_handle = true;
485
+			}
486
+			if ($wp_scripts->get_data($script_handle, 'after')) {
487
+				unset($wp_scripts->registered[ $script_handle ]->extra['after']);
488
+			}
489
+			if ($unset_handle) {
490
+				unset($this->script_handles_with_data[ $script_handle ]);
491
+			}
492
+		}
493
+	}
494
+
495
+
496
+	/**
497
+	 * @since 4.9.63.p
498
+	 * @return bool
499
+	 * @since 4.9.63.p
500
+	 */
501
+	private function debug(): bool
502
+	{
503
+		return apply_filters(
504
+			'FHEE__EventEspresso_core_services_assets_Registry__debug',
505
+			defined('EE_DEBUG') && EE_DEBUG
506
+		);
507
+	}
508
+
509
+
510
+	/**************** deprecated ****************/
511
+
512
+
513
+
514
+	/**
515
+	 * @return null
516
+	 * @deprecated $VID:$
517
+	 */
518
+	public function getI18nRegistry()
519
+	{
520
+		return null;
521
+	}
522
+
523
+
524
+	/**
525
+	 * @param string $handle
526
+	 * @deprecated $VID:$
527
+	 */
528
+	public function registerTranslation($handle)
529
+	{
530
+	}
531
+
532
+
533
+	/**
534
+	 * @param string $namespace
535
+	 * @param string $chunk_name
536
+	 * @return array
537
+	 * @deprecated $VID:$
538
+	 */
539
+	public function getCssAssetDetails($namespace, $chunk_name)
540
+	{
541
+		return [
542
+			AssetManifest::KEY_DEPENDENCIES => $this->asset_manifest->getAssetDependencies($chunk_name, Asset::TYPE_CSS),
543
+			AssetManifest::KEY_VERSION => $this->asset_manifest->getAssetVersion($chunk_name, Asset::TYPE_CSS),
544
+		];
545
+	}
546
+
547
+
548
+	/**
549
+	 * @param string $namespace
550
+	 * @param string $chunk_name
551
+	 * @return array
552
+	 * @deprecated $VID:$
553
+	 */
554
+	public function getCssDependencies($namespace, $chunk_name)
555
+	{
556
+		return $this->asset_manifest->getAssetDependencies($chunk_name, AssetManifest::ASSET_EXT_CSS);
557
+	}
558
+
559
+
560
+	/**
561
+	 * @param string $namespace
562
+	 * @param string $chunk_name
563
+	 * @return array
564
+	 * @deprecated $VID:$
565
+	 */
566
+	public function getJsAssetDetails($namespace, $chunk_name)
567
+	{
568
+		return [
569
+			AssetManifest::KEY_DEPENDENCIES => $this->asset_manifest->getAssetDependencies($chunk_name, Asset::TYPE_JS),
570
+			AssetManifest::KEY_VERSION => $this->asset_manifest->getAssetVersion($chunk_name, Asset::TYPE_JS),
571
+		];
572
+	}
573
+
574
+
575
+	/**
576
+	 * @param string $namespace
577
+	 * @param string $chunk_name
578
+	 * @return array
579
+	 * @deprecated $VID:$
580
+	 */
581
+	public function getJsDependencies($namespace, $chunk_name)
582
+	{
583
+		return $this->asset_manifest->getAssetDependencies($chunk_name);
584
+	}
585
+
586
+
587
+	/**
588
+	 * @deprecated $VID:$
589
+	 */
590
+	public function registerManifestFiles()
591
+	{
592
+	}
593
+
594
+
595
+	/**
596
+	 * @param string $namespace
597
+	 * @param string $url_base
598
+	 * @param string $manifest_file
599
+	 * @param string $manifest_file_path
600
+	 * @deprecated $VID:$
601
+	 */
602
+	public function registerManifestFile($namespace, $url_base, $manifest_file, $manifest_file_path = '')
603
+	{
604
+	}
605 605
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -83,8 +83,8 @@  discard block
 block discarded – undo
83 83
     public function addAssetCollection(AssetCollection $asset_collection)
84 84
     {
85 85
         $id = $asset_collection->collectionIdentifier();
86
-        if (! array_key_exists($id, $this->assets)) {
87
-            $this->assets[ $id ] = $asset_collection;
86
+        if ( ! array_key_exists($id, $this->assets)) {
87
+            $this->assets[$id] = $asset_collection;
88 88
         }
89 89
     }
90 90
 
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
                 $script->version(),
137 137
                 $script->loadInFooter()
138 138
             );
139
-            if (! $registered && $this->debug()) {
139
+            if ( ! $registered && $this->debug()) {
140 140
                 throw new AssetRegistrationException($script->handle());
141 141
             }
142 142
             $script->setRegistered($registered);
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
             $this->removeAlreadyRegisteredDataForScriptHandles();
203 203
             wp_add_inline_script(
204 204
                 CoreAssetManager::JS_HANDLE_JS_CORE,
205
-                'var eejsdata=' . wp_json_encode(['data' => $this->js_data]),
205
+                'var eejsdata='.wp_json_encode(['data' => $this->js_data]),
206 206
                 'before'
207 207
             );
208 208
             foreach ($this->assets as $asset_collection) {
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
     public function addData(string $key, $value)
239 239
     {
240 240
         if ($this->verifyDataNotExisting($key)) {
241
-            $this->js_data[ $key ] = $value;
241
+            $this->js_data[$key] = $value;
242 242
         }
243 243
     }
244 244
 
@@ -264,10 +264,10 @@  discard block
 block discarded – undo
264 264
     public function pushData(string $key, $value)
265 265
     {
266 266
         if (
267
-            isset($this->js_data[ $key ])
268
-            && ! is_array($this->js_data[ $key ])
267
+            isset($this->js_data[$key])
268
+            && ! is_array($this->js_data[$key])
269 269
         ) {
270
-            if (! $this->debug()) {
270
+            if ( ! $this->debug()) {
271 271
                 return;
272 272
             }
273 273
             throw new InvalidArgumentException(
@@ -282,10 +282,10 @@  discard block
 block discarded – undo
282 282
                 )
283 283
             );
284 284
         }
285
-        if (! isset($this->js_data[ $key ])) {
286
-            $this->js_data[ $key ] = is_array($value) ? $value : [$value];
285
+        if ( ! isset($this->js_data[$key])) {
286
+            $this->js_data[$key] = is_array($value) ? $value : [$value];
287 287
         } else {
288
-            $this->js_data[ $key ] = array_merge($this->js_data[ $key ], (array) $value);
288
+            $this->js_data[$key] = array_merge($this->js_data[$key], (array) $value);
289 289
         }
290 290
     }
291 291
 
@@ -300,12 +300,12 @@  discard block
 block discarded – undo
300 300
      */
301 301
     public function addTemplate(string $template_reference, string $template_content)
302 302
     {
303
-        if (! isset($this->js_data['templates'])) {
303
+        if ( ! isset($this->js_data['templates'])) {
304 304
             $this->js_data['templates'] = [];
305 305
         }
306 306
         //no overrides allowed.
307
-        if (isset($this->js_data['templates'][ $template_reference ])) {
308
-            if (! $this->debug()) {
307
+        if (isset($this->js_data['templates'][$template_reference])) {
308
+            if ( ! $this->debug()) {
309 309
                 return;
310 310
             }
311 311
             throw new InvalidArgumentException(
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
                 )
319 319
             );
320 320
         }
321
-        $this->js_data['templates'][ $template_reference ] = $template_content;
321
+        $this->js_data['templates'][$template_reference] = $template_content;
322 322
     }
323 323
 
324 324
 
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
      */
331 331
     public function getTemplate(string $template_reference): string
332 332
     {
333
-        return $this->js_data['templates'][ $template_reference ] ?? '';
333
+        return $this->js_data['templates'][$template_reference] ?? '';
334 334
     }
335 335
 
336 336
 
@@ -342,7 +342,7 @@  discard block
 block discarded – undo
342 342
      */
343 343
     public function getData(string $key)
344 344
     {
345
-        return array_key_exists($key, $this->js_data) ? $this->js_data[ $key ] : null;
345
+        return array_key_exists($key, $this->js_data) ? $this->js_data[$key] : null;
346 346
     }
347 347
 
348 348
 
@@ -356,11 +356,11 @@  discard block
 block discarded – undo
356 356
      */
357 357
     protected function verifyDataNotExisting(string $key): bool
358 358
     {
359
-        if (isset($this->js_data[ $key ])) {
360
-            if (! $this->debug()) {
359
+        if (isset($this->js_data[$key])) {
360
+            if ( ! $this->debug()) {
361 361
                 return false;
362 362
             }
363
-            if (is_array($this->js_data[ $key ])) {
363
+            if (is_array($this->js_data[$key])) {
364 364
                 throw new InvalidArgumentException(
365 365
                     sprintf(
366 366
                         esc_html__(
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
      */
446 446
     private function addRegisteredScriptHandlesWithData(string $script_handle)
447 447
     {
448
-        $this->script_handles_with_data[ $script_handle ] = $script_handle;
448
+        $this->script_handles_with_data[$script_handle] = $script_handle;
449 449
     }
450 450
 
451 451
 
@@ -471,23 +471,23 @@  discard block
 block discarded – undo
471 471
      */
472 472
     private function removeAlreadyRegisteredDataForScriptHandle(string $script_handle)
473 473
     {
474
-        if (isset($this->script_handles_with_data[ $script_handle ])) {
474
+        if (isset($this->script_handles_with_data[$script_handle])) {
475 475
             global $wp_scripts;
476 476
             $unset_handle = false;
477 477
             if ($wp_scripts->get_data($script_handle, 'data')) {
478
-                unset($wp_scripts->registered[ $script_handle ]->extra['data']);
478
+                unset($wp_scripts->registered[$script_handle]->extra['data']);
479 479
                 $unset_handle = true;
480 480
             }
481 481
             //deal with inline_scripts
482 482
             if ($wp_scripts->get_data($script_handle, 'before')) {
483
-                unset($wp_scripts->registered[ $script_handle ]->extra['before']);
483
+                unset($wp_scripts->registered[$script_handle]->extra['before']);
484 484
                 $unset_handle = true;
485 485
             }
486 486
             if ($wp_scripts->get_data($script_handle, 'after')) {
487
-                unset($wp_scripts->registered[ $script_handle ]->extra['after']);
487
+                unset($wp_scripts->registered[$script_handle]->extra['after']);
488 488
             }
489 489
             if ($unset_handle) {
490
-                unset($this->script_handles_with_data[ $script_handle ]);
490
+                unset($this->script_handles_with_data[$script_handle]);
491 491
             }
492 492
         }
493 493
     }
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1724 added lines, -1724 removed lines patch added patch discarded remove patch
@@ -22,1729 +22,1729 @@
 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 = array();
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 = array();
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 = array();
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 = array();
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
-    ) {
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', array($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
-            array(
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', array(), 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', array($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()
306
-    {
307
-        $i18n_js_strings = (array) self::$i18n_js_strings;
308
-        foreach ($i18n_js_strings as $key => $value) {
309
-            if (is_scalar($value)) {
310
-                $decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311
-                $i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
312
-            }
313
-        }
314
-        return $i18n_js_strings;
315
-    }
316
-
317
-
318
-    /**
319
-     * localize_i18n_js_strings
320
-     *
321
-     * @return string
322
-     */
323
-    public static function localize_i18n_js_strings()
324
-    {
325
-        $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
326
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
327
-    }
328
-
329
-
330
-    /**
331
-     * @param mixed string | EED_Module $module
332
-     * @throws OutOfBoundsException
333
-     * @throws InvalidArgumentException
334
-     * @throws InvalidInterfaceException
335
-     * @throws InvalidDataTypeException
336
-     * @throws EE_Error
337
-     * @throws ReflectionException
338
-     */
339
-    public function add_module($module)
340
-    {
341
-        if ($module instanceof EED_Module) {
342
-            $module_class = get_class($module);
343
-            $this->modules->add($module_class, $module);
344
-        } else {
345
-            if (! class_exists('EE_Module_Request_Router', false)) {
346
-                $this->load_core('Module_Request_Router');
347
-            }
348
-            EE_Module_Request_Router::module_factory($module);
349
-        }
350
-    }
351
-
352
-
353
-    /**
354
-     * @param string $module_name
355
-     * @return mixed EED_Module | NULL
356
-     */
357
-    public function get_module($module_name = '')
358
-    {
359
-        return $this->modules->get($module_name);
360
-    }
361
-
362
-
363
-    /**
364
-     * loads core classes - must be singletons
365
-     *
366
-     * @param string $class_name - simple class name ie: session
367
-     * @param mixed  $arguments
368
-     * @param bool   $load_only
369
-     * @return mixed
370
-     * @throws InvalidInterfaceException
371
-     * @throws InvalidDataTypeException
372
-     * @throws EE_Error
373
-     * @throws ReflectionException
374
-     * @throws InvalidArgumentException
375
-     */
376
-    public function load_core($class_name, $arguments = array(), $load_only = false)
377
-    {
378
-        $core_paths = apply_filters(
379
-            'FHEE__EE_Registry__load_core__core_paths',
380
-            array(
381
-                EE_CORE,
382
-                EE_ADMIN,
383
-                EE_CPTS,
384
-                EE_CORE . 'CPTs/',
385
-                EE_CORE . 'data_migration_scripts/',
386
-                EE_CORE . 'request_stack/',
387
-                EE_CORE . 'middleware/',
388
-            )
389
-        );
390
-        // retrieve instantiated class
391
-        return $this->_load(
392
-            $core_paths,
393
-            'EE_',
394
-            $class_name,
395
-            'core',
396
-            $arguments,
397
-            false,
398
-            true,
399
-            $load_only
400
-        );
401
-    }
402
-
403
-
404
-    /**
405
-     * loads service classes
406
-     *
407
-     * @param string $class_name - simple class name ie: session
408
-     * @param mixed  $arguments
409
-     * @param bool   $load_only
410
-     * @return mixed
411
-     * @throws InvalidInterfaceException
412
-     * @throws InvalidDataTypeException
413
-     * @throws EE_Error
414
-     * @throws ReflectionException
415
-     * @throws InvalidArgumentException
416
-     */
417
-    public function load_service($class_name, $arguments = array(), $load_only = false)
418
-    {
419
-        $service_paths = apply_filters(
420
-            'FHEE__EE_Registry__load_service__service_paths',
421
-            array(
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 EE_Data_Migration_Script_Base|mixed
445
-     * @throws InvalidInterfaceException
446
-     * @throws InvalidDataTypeException
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     * @throws InvalidArgumentException
450
-     */
451
-    public function load_dms($class_name, $arguments = array())
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 EE_Base_Class | bool
478
-     * @throws InvalidInterfaceException
479
-     * @throws InvalidDataTypeException
480
-     * @throws EE_Error
481
-     * @throws ReflectionException
482
-     * @throws InvalidArgumentException
483
-     */
484
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
485
-    {
486
-        $paths = apply_filters(
487
-            'FHEE__EE_Registry__load_class__paths',
488
-            array(
489
-                EE_CORE,
490
-                EE_CLASSES,
491
-                EE_BUSINESS,
492
-            )
493
-        );
494
-        // retrieve instantiated class
495
-        return $this->_load(
496
-            $paths,
497
-            'EE_',
498
-            $class_name,
499
-            'class',
500
-            $arguments,
501
-            $from_db,
502
-            $cache,
503
-            $load_only
504
-        );
505
-    }
506
-
507
-
508
-    /**
509
-     * loads helper classes - must be singletons
510
-     *
511
-     * @param string $class_name - simple class name ie: price
512
-     * @param mixed  $arguments
513
-     * @param bool   $load_only
514
-     * @return EEH_Base | bool
515
-     * @throws InvalidInterfaceException
516
-     * @throws InvalidDataTypeException
517
-     * @throws EE_Error
518
-     * @throws ReflectionException
519
-     * @throws InvalidArgumentException
520
-     */
521
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
522
-    {
523
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
524
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
525
-        // retrieve instantiated class
526
-        return $this->_load(
527
-            $helper_paths,
528
-            'EEH_',
529
-            $class_name,
530
-            'helper',
531
-            $arguments,
532
-            false,
533
-            true,
534
-            $load_only
535
-        );
536
-    }
537
-
538
-
539
-    /**
540
-     * loads core classes - must be singletons
541
-     *
542
-     * @param string $class_name - simple class name ie: session
543
-     * @param mixed  $arguments
544
-     * @param bool   $load_only
545
-     * @param bool   $cache      whether to cache the object or not.
546
-     * @return mixed
547
-     * @throws InvalidInterfaceException
548
-     * @throws InvalidDataTypeException
549
-     * @throws EE_Error
550
-     * @throws ReflectionException
551
-     * @throws InvalidArgumentException
552
-     */
553
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
554
-    {
555
-        $paths = array(
556
-            EE_LIBRARIES,
557
-            EE_LIBRARIES . 'messages/',
558
-            EE_LIBRARIES . 'shortcodes/',
559
-            EE_LIBRARIES . 'qtips/',
560
-            EE_LIBRARIES . 'payment_methods/',
561
-        );
562
-        // retrieve instantiated class
563
-        return $this->_load(
564
-            $paths,
565
-            'EE_',
566
-            $class_name,
567
-            'lib',
568
-            $arguments,
569
-            false,
570
-            $cache,
571
-            $load_only
572
-        );
573
-    }
574
-
575
-
576
-    /**
577
-     * loads model classes - must be singletons
578
-     *
579
-     * @param string $class_name - simple class name ie: price
580
-     * @param mixed  $arguments
581
-     * @param bool   $load_only
582
-     * @return mixed
583
-     * @throws InvalidInterfaceException
584
-     * @throws InvalidDataTypeException
585
-     * @throws EE_Error
586
-     * @throws ReflectionException
587
-     * @throws InvalidArgumentException
588
-     */
589
-    public function load_model($class_name, $arguments = array(), $load_only = false)
590
-    {
591
-        $paths = apply_filters(
592
-            'FHEE__EE_Registry__load_model__paths',
593
-            array(
594
-                EE_MODELS,
595
-                EE_CORE,
596
-            )
597
-        );
598
-        // retrieve instantiated class
599
-        return $this->_load(
600
-            $paths,
601
-            'EEM_',
602
-            $class_name,
603
-            'model',
604
-            $arguments,
605
-            false,
606
-            true,
607
-            $load_only
608
-        );
609
-    }
610
-
611
-
612
-    /**
613
-     * loads model classes - must be singletons
614
-     *
615
-     * @param string $class_name - simple class name ie: price
616
-     * @param mixed  $arguments
617
-     * @param bool   $load_only
618
-     * @return mixed | bool
619
-     * @throws InvalidInterfaceException
620
-     * @throws InvalidDataTypeException
621
-     * @throws EE_Error
622
-     * @throws ReflectionException
623
-     * @throws InvalidArgumentException
624
-     */
625
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
626
-    {
627
-        $paths = array(
628
-            EE_MODELS . 'fields/',
629
-            EE_MODELS . 'helpers/',
630
-            EE_MODELS . 'relations/',
631
-            EE_MODELS . 'strategies/',
632
-        );
633
-        // retrieve instantiated class
634
-        return $this->_load(
635
-            $paths,
636
-            'EE_',
637
-            $class_name,
638
-            '',
639
-            $arguments,
640
-            false,
641
-            true,
642
-            $load_only
643
-        );
644
-    }
645
-
646
-
647
-    /**
648
-     * Determines if $model_name is the name of an actual EE model.
649
-     *
650
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
651
-     * @return boolean
652
-     */
653
-    public function is_model_name($model_name)
654
-    {
655
-        return isset($this->models[ $model_name ]);
656
-    }
657
-
658
-
659
-    /**
660
-     * generic class loader
661
-     *
662
-     * @param string $path_to_file - directory path to file location, not including filename
663
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
664
-     * @param string $type         - file type - core? class? helper? model?
665
-     * @param mixed  $arguments
666
-     * @param bool   $load_only
667
-     * @return mixed
668
-     * @throws InvalidInterfaceException
669
-     * @throws InvalidDataTypeException
670
-     * @throws EE_Error
671
-     * @throws ReflectionException
672
-     * @throws InvalidArgumentException
673
-     */
674
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
675
-    {
676
-        // retrieve instantiated class
677
-        return $this->_load(
678
-            $path_to_file,
679
-            '',
680
-            $file_name,
681
-            $type,
682
-            $arguments,
683
-            false,
684
-            true,
685
-            $load_only
686
-        );
687
-    }
688
-
689
-
690
-    /**
691
-     * @param string $path_to_file - directory path to file location, not including filename
692
-     * @param string $class_name   - full class name  ie:  My_Class
693
-     * @param string $type         - file type - core? class? helper? model?
694
-     * @param mixed  $arguments
695
-     * @param bool   $load_only
696
-     * @return bool|EE_Addon|object
697
-     * @throws InvalidInterfaceException
698
-     * @throws InvalidDataTypeException
699
-     * @throws EE_Error
700
-     * @throws ReflectionException
701
-     * @throws InvalidArgumentException
702
-     */
703
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
704
-    {
705
-        // retrieve instantiated class
706
-        return $this->_load(
707
-            $path_to_file,
708
-            'addon',
709
-            $class_name,
710
-            $type,
711
-            $arguments,
712
-            false,
713
-            true,
714
-            $load_only
715
-        );
716
-    }
717
-
718
-
719
-    /**
720
-     * instantiates, caches, and automatically resolves dependencies
721
-     * for classes that use a Fully Qualified Class Name.
722
-     * if the class is not capable of being loaded using PSR-4 autoloading,
723
-     * then you need to use one of the existing load_*() methods
724
-     * which can resolve the classname and filepath from the passed arguments
725
-     *
726
-     * @param bool|string $class_name   Fully Qualified Class Name
727
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
728
-     * @param bool        $cache        whether to cache the instantiated object for reuse
729
-     * @param bool        $from_db      some classes are instantiated from the db
730
-     *                                  and thus call a different method to instantiate
731
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
732
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
733
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
734
-     *                                  object = class loaded and instantiated successfully.
735
-     *                                  bool = fail or success when $load_only is true
736
-     * @throws InvalidInterfaceException
737
-     * @throws InvalidDataTypeException
738
-     * @throws EE_Error
739
-     * @throws ReflectionException
740
-     * @throws InvalidArgumentException
741
-     */
742
-    public function create(
743
-        $class_name = false,
744
-        $arguments = array(),
745
-        $cache = false,
746
-        $from_db = false,
747
-        $load_only = false,
748
-        $addon = false
749
-    ) {
750
-        $class_name = ltrim($class_name, '\\');
751
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
752
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
753
-        // if a non-FQCN was passed, then
754
-        // verifyClassExists() might return an object
755
-        // or it could return null if the class just could not be found anywhere
756
-        if ($class_exists instanceof $class_name || $class_exists === null) {
757
-            // either way, return the results
758
-            return $class_exists;
759
-        }
760
-        $class_name = $class_exists;
761
-        // if we're only loading the class and it already exists, then let's just return true immediately
762
-        if ($load_only) {
763
-            return true;
764
-        }
765
-        $addon = $addon ? 'addon' : '';
766
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
767
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
768
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
769
-        if ($this->_cache_on && $cache && ! $load_only) {
770
-            // return object if it's already cached
771
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
772
-            if ($cached_class !== null) {
773
-                return $cached_class;
774
-            }
775
-        }// obtain the loader method from the dependency map
776
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
777
-        if ($loader instanceof Closure) {
778
-            $class_obj = $loader($arguments);
779
-        } else {
780
-            if ($loader && method_exists($this, $loader)) {
781
-                $class_obj = $this->{$loader}($class_name, $arguments);
782
-            } else {
783
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
784
-            }
785
-        }
786
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
787
-            // save it for later... kinda like gum  { : $
788
-            $this->_set_cached_class(
789
-                $class_obj,
790
-                $class_name,
791
-                $addon,
792
-                $from_db,
793
-                $arguments
794
-            );
795
-        }
796
-        $this->_cache_on = true;
797
-        return $class_obj;
798
-    }
799
-
800
-
801
-    /**
802
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
803
-     *
804
-     * @param string|object $class_name
805
-     * @param array         $arguments
806
-     * @param int           $attempt
807
-     * @return mixed
808
-     */
809
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
810
-    {
811
-        if (is_object($class_name) || class_exists($class_name)) {
812
-            return $class_name;
813
-        }
814
-        switch ($attempt) {
815
-            case 1:
816
-                // if it's a FQCN then maybe the class is registered with a preceding \
817
-                $class_name = strpos($class_name, '\\') !== false
818
-                    ? '\\' . ltrim($class_name, '\\')
819
-                    : $class_name;
820
-                break;
821
-            case 2:
822
-                //
823
-                $loader = $this->_dependency_map->class_loader($class_name);
824
-                if ($loader && method_exists($this, $loader)) {
825
-                    return $this->{$loader}($class_name, $arguments);
826
-                }
827
-                break;
828
-            case 3:
829
-            default:
830
-                return null;
831
-        }
832
-        $attempt++;
833
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
834
-    }
835
-
836
-
837
-    /**
838
-     * instantiates, caches, and injects dependencies for classes
839
-     *
840
-     * @param array       $file_paths   an array of paths to folders to look in
841
-     * @param string      $class_prefix EE  or EEM or... ???
842
-     * @param bool|string $class_name   $class name
843
-     * @param string      $type         file type - core? class? helper? model?
844
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
845
-     * @param bool        $from_db      some classes are instantiated from the db
846
-     *                                  and thus call a different method to instantiate
847
-     * @param bool        $cache        whether to cache the instantiated object for reuse
848
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
849
-     * @return bool|null|object null = failure to load or instantiate class object.
850
-     *                                  object = class loaded and instantiated successfully.
851
-     *                                  bool = fail or success when $load_only is true
852
-     * @throws EE_Error
853
-     * @throws ReflectionException
854
-     * @throws InvalidInterfaceException
855
-     * @throws InvalidDataTypeException
856
-     * @throws InvalidArgumentException
857
-     */
858
-    protected function _load(
859
-        $file_paths = array(),
860
-        $class_prefix = 'EE_',
861
-        $class_name = false,
862
-        $type = 'class',
863
-        $arguments = array(),
864
-        $from_db = false,
865
-        $cache = true,
866
-        $load_only = false
867
-    ) {
868
-        $class_name = ltrim($class_name, '\\');
869
-        // strip php file extension
870
-        $class_name = str_replace('.php', '', trim($class_name));
871
-        // does the class have a prefix ?
872
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
873
-            // make sure $class_prefix is uppercase
874
-            $class_prefix = strtoupper(trim($class_prefix));
875
-            // add class prefix ONCE!!!
876
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
877
-        }
878
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
879
-        $class_exists = class_exists($class_name, false);
880
-        // if we're only loading the class and it already exists, then let's just return true immediately
881
-        if ($load_only && $class_exists) {
882
-            return true;
883
-        }
884
-        $arguments = is_array($arguments) ? $arguments : array($arguments);
885
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
886
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
887
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
888
-        if ($this->_cache_on && $cache && ! $load_only) {
889
-            // return object if it's already cached
890
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
891
-            if ($cached_class !== null) {
892
-                return $cached_class;
893
-            }
894
-        }
895
-        // if the class doesn't already exist.. then we need to try and find the file and load it
896
-        if (! $class_exists) {
897
-            // get full path to file
898
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
899
-            // load the file
900
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
901
-            // if we are only loading a file but NOT instantiating an object
902
-            // then return boolean for whether class was loaded or not
903
-            if ($load_only) {
904
-                return $loaded;
905
-            }
906
-            // if an object was expected but loading failed, then return nothing
907
-            if (! $loaded) {
908
-                return null;
909
-            }
910
-        }
911
-        // instantiate the requested object
912
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
913
-        if ($this->_cache_on && $cache) {
914
-            // save it for later... kinda like gum  { : $
915
-            $this->_set_cached_class(
916
-                $class_obj,
917
-                $class_name,
918
-                $class_prefix,
919
-                $from_db,
920
-                $arguments
921
-            );
922
-        }
923
-        $this->_cache_on = true;
924
-        return $class_obj;
925
-    }
926
-
927
-
928
-    /**
929
-     * @param string $class_name
930
-     * @param string $default have to specify something, but not anything that will conflict
931
-     * @return mixed|string
932
-     */
933
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
934
-    {
935
-        return isset($this->_class_abbreviations[ $class_name ])
936
-            ? $this->_class_abbreviations[ $class_name ]
937
-            : $default;
938
-    }
939
-
940
-
941
-    /**
942
-     * attempts to find a cached version of the requested class
943
-     * by looking in the following places:
944
-     *        $this->{$class_abbreviation}            ie:    $this->CART
945
-     *        $this->{$class_name}                        ie:    $this->Some_Class
946
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
947
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
948
-     *
949
-     * @param string $class_name
950
-     * @param string $class_prefix
951
-     * @param array  $arguments
952
-     * @return mixed
953
-     */
954
-    protected function _get_cached_class(
955
-        $class_name,
956
-        $class_prefix = '',
957
-        $arguments = array()
958
-    ) {
959
-        if ($class_name === 'EE_Registry') {
960
-            return $this;
961
-        }
962
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
963
-        // check if class has already been loaded, and return it if it has been
964
-        if (isset($this->{$class_abbreviation})) {
965
-            return $this->{$class_abbreviation};
966
-        }
967
-        $class_name = str_replace('\\', '_', $class_name);
968
-        if (isset($this->{$class_name})) {
969
-            return $this->{$class_name};
970
-        }
971
-        if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
972
-            return $this->addons->get($class_name);
973
-        }
974
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
975
-        if ($this->LIB->has($object_identifier)) {
976
-            return $this->LIB->get($object_identifier);
977
-        }
978
-        foreach ($this->LIB as $key => $object) {
979
-            if (
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 = array();
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 = array();
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 = array();
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 = array();
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
+	) {
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', array($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
+			array(
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', array(), 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', array($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()
306
+	{
307
+		$i18n_js_strings = (array) self::$i18n_js_strings;
308
+		foreach ($i18n_js_strings as $key => $value) {
309
+			if (is_scalar($value)) {
310
+				$decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
311
+				$i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
312
+			}
313
+		}
314
+		return $i18n_js_strings;
315
+	}
316
+
317
+
318
+	/**
319
+	 * localize_i18n_js_strings
320
+	 *
321
+	 * @return string
322
+	 */
323
+	public static function localize_i18n_js_strings()
324
+	{
325
+		$i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
326
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
327
+	}
328
+
329
+
330
+	/**
331
+	 * @param mixed string | EED_Module $module
332
+	 * @throws OutOfBoundsException
333
+	 * @throws InvalidArgumentException
334
+	 * @throws InvalidInterfaceException
335
+	 * @throws InvalidDataTypeException
336
+	 * @throws EE_Error
337
+	 * @throws ReflectionException
338
+	 */
339
+	public function add_module($module)
340
+	{
341
+		if ($module instanceof EED_Module) {
342
+			$module_class = get_class($module);
343
+			$this->modules->add($module_class, $module);
344
+		} else {
345
+			if (! class_exists('EE_Module_Request_Router', false)) {
346
+				$this->load_core('Module_Request_Router');
347
+			}
348
+			EE_Module_Request_Router::module_factory($module);
349
+		}
350
+	}
351
+
352
+
353
+	/**
354
+	 * @param string $module_name
355
+	 * @return mixed EED_Module | NULL
356
+	 */
357
+	public function get_module($module_name = '')
358
+	{
359
+		return $this->modules->get($module_name);
360
+	}
361
+
362
+
363
+	/**
364
+	 * loads core classes - must be singletons
365
+	 *
366
+	 * @param string $class_name - simple class name ie: session
367
+	 * @param mixed  $arguments
368
+	 * @param bool   $load_only
369
+	 * @return mixed
370
+	 * @throws InvalidInterfaceException
371
+	 * @throws InvalidDataTypeException
372
+	 * @throws EE_Error
373
+	 * @throws ReflectionException
374
+	 * @throws InvalidArgumentException
375
+	 */
376
+	public function load_core($class_name, $arguments = array(), $load_only = false)
377
+	{
378
+		$core_paths = apply_filters(
379
+			'FHEE__EE_Registry__load_core__core_paths',
380
+			array(
381
+				EE_CORE,
382
+				EE_ADMIN,
383
+				EE_CPTS,
384
+				EE_CORE . 'CPTs/',
385
+				EE_CORE . 'data_migration_scripts/',
386
+				EE_CORE . 'request_stack/',
387
+				EE_CORE . 'middleware/',
388
+			)
389
+		);
390
+		// retrieve instantiated class
391
+		return $this->_load(
392
+			$core_paths,
393
+			'EE_',
394
+			$class_name,
395
+			'core',
396
+			$arguments,
397
+			false,
398
+			true,
399
+			$load_only
400
+		);
401
+	}
402
+
403
+
404
+	/**
405
+	 * loads service classes
406
+	 *
407
+	 * @param string $class_name - simple class name ie: session
408
+	 * @param mixed  $arguments
409
+	 * @param bool   $load_only
410
+	 * @return mixed
411
+	 * @throws InvalidInterfaceException
412
+	 * @throws InvalidDataTypeException
413
+	 * @throws EE_Error
414
+	 * @throws ReflectionException
415
+	 * @throws InvalidArgumentException
416
+	 */
417
+	public function load_service($class_name, $arguments = array(), $load_only = false)
418
+	{
419
+		$service_paths = apply_filters(
420
+			'FHEE__EE_Registry__load_service__service_paths',
421
+			array(
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 EE_Data_Migration_Script_Base|mixed
445
+	 * @throws InvalidInterfaceException
446
+	 * @throws InvalidDataTypeException
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 * @throws InvalidArgumentException
450
+	 */
451
+	public function load_dms($class_name, $arguments = array())
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 EE_Base_Class | bool
478
+	 * @throws InvalidInterfaceException
479
+	 * @throws InvalidDataTypeException
480
+	 * @throws EE_Error
481
+	 * @throws ReflectionException
482
+	 * @throws InvalidArgumentException
483
+	 */
484
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
485
+	{
486
+		$paths = apply_filters(
487
+			'FHEE__EE_Registry__load_class__paths',
488
+			array(
489
+				EE_CORE,
490
+				EE_CLASSES,
491
+				EE_BUSINESS,
492
+			)
493
+		);
494
+		// retrieve instantiated class
495
+		return $this->_load(
496
+			$paths,
497
+			'EE_',
498
+			$class_name,
499
+			'class',
500
+			$arguments,
501
+			$from_db,
502
+			$cache,
503
+			$load_only
504
+		);
505
+	}
506
+
507
+
508
+	/**
509
+	 * loads helper classes - must be singletons
510
+	 *
511
+	 * @param string $class_name - simple class name ie: price
512
+	 * @param mixed  $arguments
513
+	 * @param bool   $load_only
514
+	 * @return EEH_Base | bool
515
+	 * @throws InvalidInterfaceException
516
+	 * @throws InvalidDataTypeException
517
+	 * @throws EE_Error
518
+	 * @throws ReflectionException
519
+	 * @throws InvalidArgumentException
520
+	 */
521
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
522
+	{
523
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
524
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
525
+		// retrieve instantiated class
526
+		return $this->_load(
527
+			$helper_paths,
528
+			'EEH_',
529
+			$class_name,
530
+			'helper',
531
+			$arguments,
532
+			false,
533
+			true,
534
+			$load_only
535
+		);
536
+	}
537
+
538
+
539
+	/**
540
+	 * loads core classes - must be singletons
541
+	 *
542
+	 * @param string $class_name - simple class name ie: session
543
+	 * @param mixed  $arguments
544
+	 * @param bool   $load_only
545
+	 * @param bool   $cache      whether to cache the object or not.
546
+	 * @return mixed
547
+	 * @throws InvalidInterfaceException
548
+	 * @throws InvalidDataTypeException
549
+	 * @throws EE_Error
550
+	 * @throws ReflectionException
551
+	 * @throws InvalidArgumentException
552
+	 */
553
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
554
+	{
555
+		$paths = array(
556
+			EE_LIBRARIES,
557
+			EE_LIBRARIES . 'messages/',
558
+			EE_LIBRARIES . 'shortcodes/',
559
+			EE_LIBRARIES . 'qtips/',
560
+			EE_LIBRARIES . 'payment_methods/',
561
+		);
562
+		// retrieve instantiated class
563
+		return $this->_load(
564
+			$paths,
565
+			'EE_',
566
+			$class_name,
567
+			'lib',
568
+			$arguments,
569
+			false,
570
+			$cache,
571
+			$load_only
572
+		);
573
+	}
574
+
575
+
576
+	/**
577
+	 * loads model classes - must be singletons
578
+	 *
579
+	 * @param string $class_name - simple class name ie: price
580
+	 * @param mixed  $arguments
581
+	 * @param bool   $load_only
582
+	 * @return mixed
583
+	 * @throws InvalidInterfaceException
584
+	 * @throws InvalidDataTypeException
585
+	 * @throws EE_Error
586
+	 * @throws ReflectionException
587
+	 * @throws InvalidArgumentException
588
+	 */
589
+	public function load_model($class_name, $arguments = array(), $load_only = false)
590
+	{
591
+		$paths = apply_filters(
592
+			'FHEE__EE_Registry__load_model__paths',
593
+			array(
594
+				EE_MODELS,
595
+				EE_CORE,
596
+			)
597
+		);
598
+		// retrieve instantiated class
599
+		return $this->_load(
600
+			$paths,
601
+			'EEM_',
602
+			$class_name,
603
+			'model',
604
+			$arguments,
605
+			false,
606
+			true,
607
+			$load_only
608
+		);
609
+	}
610
+
611
+
612
+	/**
613
+	 * loads model classes - must be singletons
614
+	 *
615
+	 * @param string $class_name - simple class name ie: price
616
+	 * @param mixed  $arguments
617
+	 * @param bool   $load_only
618
+	 * @return mixed | bool
619
+	 * @throws InvalidInterfaceException
620
+	 * @throws InvalidDataTypeException
621
+	 * @throws EE_Error
622
+	 * @throws ReflectionException
623
+	 * @throws InvalidArgumentException
624
+	 */
625
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
626
+	{
627
+		$paths = array(
628
+			EE_MODELS . 'fields/',
629
+			EE_MODELS . 'helpers/',
630
+			EE_MODELS . 'relations/',
631
+			EE_MODELS . 'strategies/',
632
+		);
633
+		// retrieve instantiated class
634
+		return $this->_load(
635
+			$paths,
636
+			'EE_',
637
+			$class_name,
638
+			'',
639
+			$arguments,
640
+			false,
641
+			true,
642
+			$load_only
643
+		);
644
+	}
645
+
646
+
647
+	/**
648
+	 * Determines if $model_name is the name of an actual EE model.
649
+	 *
650
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
651
+	 * @return boolean
652
+	 */
653
+	public function is_model_name($model_name)
654
+	{
655
+		return isset($this->models[ $model_name ]);
656
+	}
657
+
658
+
659
+	/**
660
+	 * generic class loader
661
+	 *
662
+	 * @param string $path_to_file - directory path to file location, not including filename
663
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
664
+	 * @param string $type         - file type - core? class? helper? model?
665
+	 * @param mixed  $arguments
666
+	 * @param bool   $load_only
667
+	 * @return mixed
668
+	 * @throws InvalidInterfaceException
669
+	 * @throws InvalidDataTypeException
670
+	 * @throws EE_Error
671
+	 * @throws ReflectionException
672
+	 * @throws InvalidArgumentException
673
+	 */
674
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
675
+	{
676
+		// retrieve instantiated class
677
+		return $this->_load(
678
+			$path_to_file,
679
+			'',
680
+			$file_name,
681
+			$type,
682
+			$arguments,
683
+			false,
684
+			true,
685
+			$load_only
686
+		);
687
+	}
688
+
689
+
690
+	/**
691
+	 * @param string $path_to_file - directory path to file location, not including filename
692
+	 * @param string $class_name   - full class name  ie:  My_Class
693
+	 * @param string $type         - file type - core? class? helper? model?
694
+	 * @param mixed  $arguments
695
+	 * @param bool   $load_only
696
+	 * @return bool|EE_Addon|object
697
+	 * @throws InvalidInterfaceException
698
+	 * @throws InvalidDataTypeException
699
+	 * @throws EE_Error
700
+	 * @throws ReflectionException
701
+	 * @throws InvalidArgumentException
702
+	 */
703
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
704
+	{
705
+		// retrieve instantiated class
706
+		return $this->_load(
707
+			$path_to_file,
708
+			'addon',
709
+			$class_name,
710
+			$type,
711
+			$arguments,
712
+			false,
713
+			true,
714
+			$load_only
715
+		);
716
+	}
717
+
718
+
719
+	/**
720
+	 * instantiates, caches, and automatically resolves dependencies
721
+	 * for classes that use a Fully Qualified Class Name.
722
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
723
+	 * then you need to use one of the existing load_*() methods
724
+	 * which can resolve the classname and filepath from the passed arguments
725
+	 *
726
+	 * @param bool|string $class_name   Fully Qualified Class Name
727
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
728
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
729
+	 * @param bool        $from_db      some classes are instantiated from the db
730
+	 *                                  and thus call a different method to instantiate
731
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
732
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
733
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
734
+	 *                                  object = class loaded and instantiated successfully.
735
+	 *                                  bool = fail or success when $load_only is true
736
+	 * @throws InvalidInterfaceException
737
+	 * @throws InvalidDataTypeException
738
+	 * @throws EE_Error
739
+	 * @throws ReflectionException
740
+	 * @throws InvalidArgumentException
741
+	 */
742
+	public function create(
743
+		$class_name = false,
744
+		$arguments = array(),
745
+		$cache = false,
746
+		$from_db = false,
747
+		$load_only = false,
748
+		$addon = false
749
+	) {
750
+		$class_name = ltrim($class_name, '\\');
751
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
752
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
753
+		// if a non-FQCN was passed, then
754
+		// verifyClassExists() might return an object
755
+		// or it could return null if the class just could not be found anywhere
756
+		if ($class_exists instanceof $class_name || $class_exists === null) {
757
+			// either way, return the results
758
+			return $class_exists;
759
+		}
760
+		$class_name = $class_exists;
761
+		// if we're only loading the class and it already exists, then let's just return true immediately
762
+		if ($load_only) {
763
+			return true;
764
+		}
765
+		$addon = $addon ? 'addon' : '';
766
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
767
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
768
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
769
+		if ($this->_cache_on && $cache && ! $load_only) {
770
+			// return object if it's already cached
771
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
772
+			if ($cached_class !== null) {
773
+				return $cached_class;
774
+			}
775
+		}// obtain the loader method from the dependency map
776
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
777
+		if ($loader instanceof Closure) {
778
+			$class_obj = $loader($arguments);
779
+		} else {
780
+			if ($loader && method_exists($this, $loader)) {
781
+				$class_obj = $this->{$loader}($class_name, $arguments);
782
+			} else {
783
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
784
+			}
785
+		}
786
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
787
+			// save it for later... kinda like gum  { : $
788
+			$this->_set_cached_class(
789
+				$class_obj,
790
+				$class_name,
791
+				$addon,
792
+				$from_db,
793
+				$arguments
794
+			);
795
+		}
796
+		$this->_cache_on = true;
797
+		return $class_obj;
798
+	}
799
+
800
+
801
+	/**
802
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
803
+	 *
804
+	 * @param string|object $class_name
805
+	 * @param array         $arguments
806
+	 * @param int           $attempt
807
+	 * @return mixed
808
+	 */
809
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
810
+	{
811
+		if (is_object($class_name) || class_exists($class_name)) {
812
+			return $class_name;
813
+		}
814
+		switch ($attempt) {
815
+			case 1:
816
+				// if it's a FQCN then maybe the class is registered with a preceding \
817
+				$class_name = strpos($class_name, '\\') !== false
818
+					? '\\' . ltrim($class_name, '\\')
819
+					: $class_name;
820
+				break;
821
+			case 2:
822
+				//
823
+				$loader = $this->_dependency_map->class_loader($class_name);
824
+				if ($loader && method_exists($this, $loader)) {
825
+					return $this->{$loader}($class_name, $arguments);
826
+				}
827
+				break;
828
+			case 3:
829
+			default:
830
+				return null;
831
+		}
832
+		$attempt++;
833
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
834
+	}
835
+
836
+
837
+	/**
838
+	 * instantiates, caches, and injects dependencies for classes
839
+	 *
840
+	 * @param array       $file_paths   an array of paths to folders to look in
841
+	 * @param string      $class_prefix EE  or EEM or... ???
842
+	 * @param bool|string $class_name   $class name
843
+	 * @param string      $type         file type - core? class? helper? model?
844
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
845
+	 * @param bool        $from_db      some classes are instantiated from the db
846
+	 *                                  and thus call a different method to instantiate
847
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
848
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
849
+	 * @return bool|null|object null = failure to load or instantiate class object.
850
+	 *                                  object = class loaded and instantiated successfully.
851
+	 *                                  bool = fail or success when $load_only is true
852
+	 * @throws EE_Error
853
+	 * @throws ReflectionException
854
+	 * @throws InvalidInterfaceException
855
+	 * @throws InvalidDataTypeException
856
+	 * @throws InvalidArgumentException
857
+	 */
858
+	protected function _load(
859
+		$file_paths = array(),
860
+		$class_prefix = 'EE_',
861
+		$class_name = false,
862
+		$type = 'class',
863
+		$arguments = array(),
864
+		$from_db = false,
865
+		$cache = true,
866
+		$load_only = false
867
+	) {
868
+		$class_name = ltrim($class_name, '\\');
869
+		// strip php file extension
870
+		$class_name = str_replace('.php', '', trim($class_name));
871
+		// does the class have a prefix ?
872
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
873
+			// make sure $class_prefix is uppercase
874
+			$class_prefix = strtoupper(trim($class_prefix));
875
+			// add class prefix ONCE!!!
876
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
877
+		}
878
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
879
+		$class_exists = class_exists($class_name, false);
880
+		// if we're only loading the class and it already exists, then let's just return true immediately
881
+		if ($load_only && $class_exists) {
882
+			return true;
883
+		}
884
+		$arguments = is_array($arguments) ? $arguments : array($arguments);
885
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
886
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
887
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
888
+		if ($this->_cache_on && $cache && ! $load_only) {
889
+			// return object if it's already cached
890
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
891
+			if ($cached_class !== null) {
892
+				return $cached_class;
893
+			}
894
+		}
895
+		// if the class doesn't already exist.. then we need to try and find the file and load it
896
+		if (! $class_exists) {
897
+			// get full path to file
898
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
899
+			// load the file
900
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
901
+			// if we are only loading a file but NOT instantiating an object
902
+			// then return boolean for whether class was loaded or not
903
+			if ($load_only) {
904
+				return $loaded;
905
+			}
906
+			// if an object was expected but loading failed, then return nothing
907
+			if (! $loaded) {
908
+				return null;
909
+			}
910
+		}
911
+		// instantiate the requested object
912
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
913
+		if ($this->_cache_on && $cache) {
914
+			// save it for later... kinda like gum  { : $
915
+			$this->_set_cached_class(
916
+				$class_obj,
917
+				$class_name,
918
+				$class_prefix,
919
+				$from_db,
920
+				$arguments
921
+			);
922
+		}
923
+		$this->_cache_on = true;
924
+		return $class_obj;
925
+	}
926
+
927
+
928
+	/**
929
+	 * @param string $class_name
930
+	 * @param string $default have to specify something, but not anything that will conflict
931
+	 * @return mixed|string
932
+	 */
933
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
934
+	{
935
+		return isset($this->_class_abbreviations[ $class_name ])
936
+			? $this->_class_abbreviations[ $class_name ]
937
+			: $default;
938
+	}
939
+
940
+
941
+	/**
942
+	 * attempts to find a cached version of the requested class
943
+	 * by looking in the following places:
944
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
945
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
946
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
947
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
948
+	 *
949
+	 * @param string $class_name
950
+	 * @param string $class_prefix
951
+	 * @param array  $arguments
952
+	 * @return mixed
953
+	 */
954
+	protected function _get_cached_class(
955
+		$class_name,
956
+		$class_prefix = '',
957
+		$arguments = array()
958
+	) {
959
+		if ($class_name === 'EE_Registry') {
960
+			return $this;
961
+		}
962
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
963
+		// check if class has already been loaded, and return it if it has been
964
+		if (isset($this->{$class_abbreviation})) {
965
+			return $this->{$class_abbreviation};
966
+		}
967
+		$class_name = str_replace('\\', '_', $class_name);
968
+		if (isset($this->{$class_name})) {
969
+			return $this->{$class_name};
970
+		}
971
+		if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
972
+			return $this->addons->get($class_name);
973
+		}
974
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
975
+		if ($this->LIB->has($object_identifier)) {
976
+			return $this->LIB->get($object_identifier);
977
+		}
978
+		foreach ($this->LIB as $key => $object) {
979
+			if (
980 980
 // request does not contain new arguments and therefore no args identifier
981
-                ! $this->object_identifier->hasArguments($object_identifier)
982
-                // but previously cached class with args was found
983
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
984
-            ) {
985
-                return $object;
986
-            }
987
-        }
988
-        return null;
989
-    }
990
-
991
-
992
-    /**
993
-     * removes a cached version of the requested class
994
-     *
995
-     * @param string  $class_name
996
-     * @param boolean $addon
997
-     * @param array   $arguments
998
-     * @return boolean
999
-     */
1000
-    public function clear_cached_class(
1001
-        $class_name,
1002
-        $addon = false,
1003
-        $arguments = array()
1004
-    ) {
1005
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
1006
-        // check if class has already been loaded, and return it if it has been
1007
-        if (isset($this->{$class_abbreviation})) {
1008
-            $this->{$class_abbreviation} = null;
1009
-            return true;
1010
-        }
1011
-        $class_name = str_replace('\\', '_', $class_name);
1012
-        if (isset($this->{$class_name})) {
1013
-            $this->{$class_name} = null;
1014
-            return true;
1015
-        }
1016
-        if ($addon && $this->addons->has($class_name)) {
1017
-            $this->addons->remove($class_name);
1018
-            return true;
1019
-        }
1020
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1021
-        if ($this->LIB->has($class_name)) {
1022
-            $this->LIB->remove($class_name);
1023
-            return true;
1024
-        }
1025
-        return false;
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     * _set_cached_class
1031
-     * attempts to cache the instantiated class locally
1032
-     * in one of the following places, in the following order:
1033
-     *        $this->{class_abbreviation}   ie:    $this->CART
1034
-     *        $this->{$class_name}          ie:    $this->Some_Class
1035
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1036
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1037
-     *
1038
-     * @param object $class_obj
1039
-     * @param string $class_name
1040
-     * @param string $class_prefix
1041
-     * @param bool   $from_db
1042
-     * @param array  $arguments
1043
-     * @return void
1044
-     */
1045
-    protected function _set_cached_class(
1046
-        $class_obj,
1047
-        $class_name,
1048
-        $class_prefix = '',
1049
-        $from_db = false,
1050
-        $arguments = array()
1051
-    ) {
1052
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1053
-            return;
1054
-        }
1055
-        // return newly instantiated class
1056
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1057
-        if ($class_abbreviation) {
1058
-            $this->{$class_abbreviation} = $class_obj;
1059
-            return;
1060
-        }
1061
-        $class_name = str_replace('\\', '_', $class_name);
1062
-        if (property_exists($this, $class_name)) {
1063
-            $this->{$class_name} = $class_obj;
1064
-            return;
1065
-        }
1066
-        if ($class_prefix === 'addon') {
1067
-            $this->addons->add($class_name, $class_obj);
1068
-            return;
1069
-        }
1070
-        if (! $from_db) {
1071
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1072
-            $this->LIB->add($class_name, $class_obj);
1073
-        }
1074
-    }
1075
-
1076
-
1077
-    /**
1078
-     * attempts to find a full valid filepath for the requested class.
1079
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1080
-     * then returns that path if the target file has been found and is readable
1081
-     *
1082
-     * @param string $class_name
1083
-     * @param string $type
1084
-     * @param array  $file_paths
1085
-     * @return string | bool
1086
-     */
1087
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
1088
-    {
1089
-        // make sure $file_paths is an array
1090
-        $file_paths = is_array($file_paths)
1091
-            ? $file_paths
1092
-            : array($file_paths);
1093
-        // cycle thru paths
1094
-        foreach ($file_paths as $key => $file_path) {
1095
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1096
-            $file_path = $file_path
1097
-                ? str_replace(array('/', '\\'), '/', $file_path)
1098
-                : EE_CLASSES;
1099
-            // prep file type
1100
-            $type = ! empty($type)
1101
-                ? trim($type, '.') . '.'
1102
-                : '';
1103
-            // build full file path
1104
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1105
-            // does the file exist and can be read ?
1106
-            if (is_readable($file_paths[ $key ])) {
1107
-                return $file_paths[ $key ];
1108
-            }
1109
-        }
1110
-        return false;
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * basically just performs a require_once()
1116
-     * but with some error handling
1117
-     *
1118
-     * @param  string $path
1119
-     * @param  string $class_name
1120
-     * @param  string $type
1121
-     * @param  array  $file_paths
1122
-     * @return bool
1123
-     * @throws EE_Error
1124
-     * @throws ReflectionException
1125
-     */
1126
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1127
-    {
1128
-        $this->resolve_legacy_class_parent($class_name);
1129
-        // don't give up! you gotta...
1130
-        try {
1131
-            // does the file exist and can it be read ?
1132
-            if (! $path) {
1133
-                // just in case the file has already been autoloaded,
1134
-                // but discrepancies in the naming schema are preventing it from
1135
-                // being loaded via one of the EE_Registry::load_*() methods,
1136
-                // then let's try one last hail mary before throwing an exception
1137
-                // and call class_exists() again, but with autoloading turned ON
1138
-                if (class_exists($class_name)) {
1139
-                    return true;
1140
-                }
1141
-                // so sorry, can't find the file
1142
-                throw new EE_Error(
1143
-                    sprintf(
1144
-                        esc_html__(
1145
-                            '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',
1146
-                            'event_espresso'
1147
-                        ),
1148
-                        trim($type, '.'),
1149
-                        $class_name,
1150
-                        '<br />' . implode(',<br />', $file_paths)
1151
-                    )
1152
-                );
1153
-            }
1154
-            // get the file
1155
-            require_once($path);
1156
-            // if the class isn't already declared somewhere
1157
-            if (class_exists($class_name, false) === false) {
1158
-                // so sorry, not a class
1159
-                throw new EE_Error(
1160
-                    sprintf(
1161
-                        esc_html__(
1162
-                            'The %s file %s does not appear to contain the %s Class.',
1163
-                            'event_espresso'
1164
-                        ),
1165
-                        $type,
1166
-                        $path,
1167
-                        $class_name
1168
-                    )
1169
-                );
1170
-            }
1171
-        } catch (EE_Error $e) {
1172
-            $e->get_error();
1173
-            return false;
1174
-        }
1175
-        return true;
1176
-    }
1177
-
1178
-
1179
-    /**
1180
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1181
-     * before their class declaration in order to ensure that the parent class was loaded.
1182
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1183
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1184
-     *
1185
-     * @param string $class_name
1186
-     */
1187
-    protected function resolve_legacy_class_parent($class_name = '')
1188
-    {
1189
-        try {
1190
-            $legacy_parent_class_map = array(
1191
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1192
-            );
1193
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1194
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1195
-            }
1196
-        } catch (Exception $exception) {
1197
-        }
1198
-    }
1199
-
1200
-
1201
-    /**
1202
-     * _create_object
1203
-     * Attempts to instantiate the requested class via any of the
1204
-     * commonly used instantiation methods employed throughout EE.
1205
-     * The priority for instantiation is as follows:
1206
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1207
-     *        - model objects via their 'new_instance_from_db' method
1208
-     *        - model objects via their 'new_instance' method
1209
-     *        - "singleton" classes" via their 'instance' method
1210
-     *    - standard instantiable classes via their __constructor
1211
-     * Prior to instantiation, if the classname exists in the dependency_map,
1212
-     * then the constructor for the requested class will be examined to determine
1213
-     * if any dependencies exist, and if they can be injected.
1214
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1215
-     *
1216
-     * @param string $class_name
1217
-     * @param array  $arguments
1218
-     * @param string $type
1219
-     * @param bool   $from_db
1220
-     * @return null|object|bool
1221
-     * @throws InvalidArgumentException
1222
-     * @throws InvalidInterfaceException
1223
-     * @throws EE_Error
1224
-     * @throws ReflectionException
1225
-     * @throws InvalidDataTypeException
1226
-     */
1227
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1228
-    {
1229
-        // create reflection
1230
-        $reflector = $this->mirror->getReflectionClass($class_name);
1231
-        // make sure arguments are an array
1232
-        $arguments = is_array($arguments)
1233
-            ? $arguments
1234
-            : array($arguments);
1235
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1236
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1237
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1238
-            ? $arguments
1239
-            : array($arguments);
1240
-        // attempt to inject dependencies ?
1241
-        if ($this->_dependency_map->has($class_name)) {
1242
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1243
-        }
1244
-        // instantiate the class if possible
1245
-        if ($reflector->isAbstract()) {
1246
-            // nothing to instantiate, loading file was enough
1247
-            // does not throw an exception so $instantiation_mode is unused
1248
-            // $instantiation_mode = "1) no constructor abstract class";
1249
-            return true;
1250
-        }
1251
-        if (
1252
-            empty($arguments)
1253
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1254
-            && $reflector->isInstantiable()
1255
-        ) {
1256
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1257
-            // $instantiation_mode = "2) no constructor but instantiable";
1258
-            return $reflector->newInstance();
1259
-        }
1260
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1261
-            // $instantiation_mode = "3) new_instance_from_db()";
1262
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1263
-        }
1264
-        if (method_exists($class_name, 'new_instance')) {
1265
-            // $instantiation_mode = "4) new_instance()";
1266
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1267
-        }
1268
-        if (method_exists($class_name, 'instance')) {
1269
-            // $instantiation_mode = "5) instance()";
1270
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1271
-        }
1272
-        if ($reflector->isInstantiable()) {
1273
-            $args_passed_count = count($arguments);
1274
-            $args_required_count = count($this->mirror->getRequiredParameters($class_name));
1275
-            if ($args_passed_count < $args_required_count) {
1276
-                throw new RuntimeException(
1277
-                    sprintf(
1278
-                        __(
1279
-                            'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1280
-                            'event_espresso'
1281
-                        ),
1282
-                        $class_name,
1283
-                        $args_required_count,
1284
-                        $args_passed_count
1285
-                    )
1286
-                );
1287
-            }
1288
-            // $instantiation_mode = "6) constructor";
1289
-            return $reflector->newInstanceArgs($arguments);
1290
-        }
1291
-        // heh ? something's not right !
1292
-        throw new EE_Error(
1293
-            sprintf(
1294
-                esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1295
-                $type,
1296
-                $class_name
1297
-            )
1298
-        );
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1304
-     * @param array $array
1305
-     * @return bool
1306
-     */
1307
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1308
-    {
1309
-        return ! empty($array)
1310
-            ? array_keys($array) === range(0, count($array) - 1)
1311
-            : true;
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * _resolve_dependencies
1317
-     * examines the constructor for the requested class to determine
1318
-     * if any dependencies exist, and if they can be injected.
1319
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1320
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1321
-     * For example:
1322
-     *        if attempting to load a class "Foo" with the following constructor:
1323
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1324
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1325
-     *        but only IF they are NOT already present in the incoming arguments array,
1326
-     *        and the correct classes can be loaded
1327
-     *
1328
-     * @param ReflectionClass $reflector
1329
-     * @param string          $class_name
1330
-     * @param array           $arguments
1331
-     * @return array
1332
-     * @throws InvalidArgumentException
1333
-     * @throws InvalidDataTypeException
1334
-     * @throws InvalidInterfaceException
1335
-     * @throws ReflectionException
1336
-     */
1337
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1338
-    {
1339
-        // let's examine the constructor
1340
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1341
-        // whu? huh? nothing?
1342
-        if (! $constructor) {
1343
-            return $arguments;
1344
-        }
1345
-        // get constructor parameters
1346
-        $params = $this->mirror->getParametersFromReflection($reflector);
1347
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1348
-        $argument_keys = array_keys($arguments);
1349
-        // now loop thru all of the constructors expected parameters
1350
-        foreach ($params as $index => $param) {
1351
-            try {
1352
-                // is this a dependency for a specific class ?
1353
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1354
-            } catch (ReflectionException $exception) {
1355
-                // uh-oh... most likely a legacy class that has not been autoloaded
1356
-                // let's try to derive the classname from what we have now
1357
-                // and hope that the property var name is close to the class name
1358
-                $param_class = $param->getName();
1359
-                $param_class = str_replace('_', ' ', $param_class);
1360
-                $param_class = ucwords($param_class);
1361
-                $param_class = str_replace(' ', '_', $param_class);
1362
-            }
1363
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1364
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1365
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1366
-                : $param_class;
1367
-            if (
1368
-                // param is not even a class
1369
-                ($param_class === null || $this->parameterIsPrimitive($param_class))
1370
-                // and something already exists in the incoming arguments for this param
1371
-                && array_key_exists($index, $argument_keys)
1372
-                && array_key_exists($argument_keys[ $index ], $arguments)
1373
-            ) {
1374
-                // so let's skip this argument and move on to the next
1375
-                continue;
1376
-            }
1377
-            if (
1378
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1379
-                $param_class !== null
1380
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1381
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1382
-            ) {
1383
-                // skip this argument and move on to the next
1384
-                continue;
1385
-            }
1386
-            if (
1387
-                // parameter is type hinted as a class, and should be injected
1388
-                $param_class !== null
1389
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1390
-            ) {
1391
-                $arguments = $this->_resolve_dependency(
1392
-                    $class_name,
1393
-                    $param_class,
1394
-                    $arguments,
1395
-                    $index
1396
-                );
1397
-            }
1398
-            if (empty($arguments[ $index ])) {
1399
-                $default_value = $this->mirror->getParameterDefaultValue(
1400
-                    $param,
1401
-                    $class_name,
1402
-                    $index
1403
-                );
1404
-                // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1405
-                $arguments[ $index ] = $default_value === null
1406
-                                 && isset($arguments[ $index ])
1407
-                                 && is_array($arguments[ $index ])
1408
-                    ? $arguments[ $index ]
1409
-                    : $default_value;
1410
-            }
1411
-        }
1412
-        return $arguments;
1413
-    }
1414
-
1415
-
1416
-    /**
1417
-     * @param string $class_name
1418
-     * @param string $param_class
1419
-     * @param array  $arguments
1420
-     * @param mixed  $index
1421
-     * @return array
1422
-     * @throws InvalidArgumentException
1423
-     * @throws InvalidInterfaceException
1424
-     * @throws InvalidDataTypeException
1425
-     */
1426
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1427
-    {
1428
-        $dependency = null;
1429
-        // should dependency be loaded from cache ?
1430
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1431
-            $class_name,
1432
-            $param_class
1433
-        );
1434
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1435
-        // we might have a dependency...
1436
-        // let's MAYBE try and find it in our cache if that's what's been requested
1437
-        $cached_class = $cache_on
1438
-            ? $this->_get_cached_class($param_class)
1439
-            : null;
1440
-        // and grab it if it exists
1441
-        if ($cached_class instanceof $param_class) {
1442
-            $dependency = $cached_class;
1443
-        } elseif ($param_class !== $class_name) {
1444
-            // obtain the loader method from the dependency map
1445
-            $loader = $this->_dependency_map->class_loader($param_class);
1446
-            // is loader a custom closure ?
1447
-            if ($loader instanceof Closure) {
1448
-                $dependency = $loader($arguments);
1449
-            } else {
1450
-                // set the cache on property for the recursive loading call
1451
-                $this->_cache_on = $cache_on;
1452
-                // if not, then let's try and load it via the registry
1453
-                if ($loader && method_exists($this, $loader)) {
1454
-                    $dependency = $this->{$loader}($param_class);
1455
-                } else {
1456
-                    $dependency = LoaderFactory::getLoader()->load(
1457
-                        $param_class,
1458
-                        array(),
1459
-                        $cache_on
1460
-                    );
1461
-                }
1462
-            }
1463
-        }
1464
-        // did we successfully find the correct dependency ?
1465
-        if ($dependency instanceof $param_class) {
1466
-            // then let's inject it into the incoming array of arguments at the correct location
1467
-            $arguments[ $index ] = $dependency;
1468
-        }
1469
-        return $arguments;
1470
-    }
1471
-
1472
-
1473
-    /**
1474
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1475
-     *
1476
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1477
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1478
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1479
-     * @param array  $arguments
1480
-     * @return object
1481
-     */
1482
-    public static function factory($classname, $arguments = array())
1483
-    {
1484
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1485
-        if ($loader instanceof Closure) {
1486
-            return $loader($arguments);
1487
-        }
1488
-        if (method_exists(self::instance(), $loader)) {
1489
-            return self::instance()->{$loader}($classname, $arguments);
1490
-        }
1491
-        return null;
1492
-    }
1493
-
1494
-
1495
-    /**
1496
-     * Gets the addon by its class name
1497
-     *
1498
-     * @param string $class_name
1499
-     * @return EE_Addon
1500
-     */
1501
-    public function getAddon($class_name)
1502
-    {
1503
-        $class_name = str_replace('\\', '_', $class_name);
1504
-        if (isset($this->addons->{$class_name})) {
1505
-            return $this->addons->{$class_name};
1506
-        } else {
1507
-            return null;
1508
-        }
1509
-    }
1510
-
1511
-
1512
-    /**
1513
-     * removes the addon from the internal cache
1514
-     *
1515
-     * @param string $class_name
1516
-     * @return void
1517
-     */
1518
-    public function removeAddon($class_name)
1519
-    {
1520
-        $class_name = str_replace('\\', '_', $class_name);
1521
-        $this->addons->remove($class_name);
1522
-    }
1523
-
1524
-
1525
-    /**
1526
-     * Gets the addon by its name/slug (not classname. For that, just
1527
-     * use the get_addon() method above
1528
-     *
1529
-     * @param string $name
1530
-     * @return EE_Addon
1531
-     */
1532
-    public function get_addon_by_name($name)
1533
-    {
1534
-        foreach ($this->addons as $addon) {
1535
-            if ($addon->name() === $name) {
1536
-                return $addon;
1537
-            }
1538
-        }
1539
-        return null;
1540
-    }
1541
-
1542
-
1543
-    /**
1544
-     * Gets an array of all the registered addons, where the keys are their names.
1545
-     * (ie, what each returns for their name() function)
1546
-     * They're already available on EE_Registry::instance()->addons as properties,
1547
-     * where each property's name is the addon's classname,
1548
-     * So if you just want to get the addon by classname,
1549
-     * OR use the get_addon() method above.
1550
-     * PLEASE  NOTE:
1551
-     * addons with Fully Qualified Class Names
1552
-     * have had the namespace separators converted to underscores,
1553
-     * so a classname like Fully\Qualified\ClassName
1554
-     * would have been converted to Fully_Qualified_ClassName
1555
-     *
1556
-     * @return EE_Addon[] where the KEYS are the addon's name()
1557
-     */
1558
-    public function get_addons_by_name()
1559
-    {
1560
-        $addons = array();
1561
-        foreach ($this->addons as $addon) {
1562
-            $addons[ $addon->name() ] = $addon;
1563
-        }
1564
-        return $addons;
1565
-    }
1566
-
1567
-
1568
-    /**
1569
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1570
-     * a stale copy of it around
1571
-     *
1572
-     * @param string $model_name
1573
-     * @return \EEM_Base
1574
-     * @throws \EE_Error
1575
-     */
1576
-    public function reset_model($model_name)
1577
-    {
1578
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1579
-            ? "EEM_{$model_name}"
1580
-            : $model_name;
1581
-        if (! $this->LIB->has($model_class_name)) {
1582
-            return null;
1583
-        }
1584
-        $model = $this->LIB->get($model_class_name);
1585
-        if (! $model instanceof EEM_Base) {
1586
-            return null;
1587
-        }
1588
-        // get that model reset it and make sure we nuke the old reference to it
1589
-        if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1590
-            $this->LIB->remove($model_class_name);
1591
-            $this->LIB->add($model_class_name, $model->reset());
1592
-        } else {
1593
-            throw new EE_Error(
1594
-                sprintf(
1595
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1596
-                    $model_name
1597
-                )
1598
-            );
1599
-        }
1600
-        return $model;
1601
-    }
1602
-
1603
-
1604
-    /**
1605
-     * Resets the registry.
1606
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1607
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1608
-     * - $_dependency_map
1609
-     * - $_class_abbreviations
1610
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1611
-     * - $REQ:  Still on the same request so no need to change.
1612
-     * - $CAP: There is no site specific state in the EE_Capability class.
1613
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1614
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1615
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1616
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1617
-     *             switch or on the restore.
1618
-     * - $modules
1619
-     * - $shortcodes
1620
-     * - $widgets
1621
-     *
1622
-     * @param boolean $hard             [deprecated]
1623
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1624
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1625
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1626
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1627
-     *                                  client
1628
-     *                                  code instead can just change the model context to a different blog id if
1629
-     *                                  necessary
1630
-     * @return EE_Registry
1631
-     * @throws InvalidInterfaceException
1632
-     * @throws InvalidDataTypeException
1633
-     * @throws EE_Error
1634
-     * @throws ReflectionException
1635
-     * @throws InvalidArgumentException
1636
-     */
1637
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
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
-        // messages reset
1648
-        EED_Messages::reset();
1649
-        // handle of objects cached on LIB
1650
-        foreach (array('LIB', 'modules') as $cache) {
1651
-            foreach ($instance->{$cache} as $class_name => $class) {
1652
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1653
-                    unset($instance->{$cache}->{$class_name});
1654
-                }
1655
-            }
1656
-        }
1657
-        return $instance;
1658
-    }
1659
-
1660
-
1661
-    /**
1662
-     * if passed object implements ResettableInterface, then call it's reset() method
1663
-     * if passed object implements InterminableInterface, then return false,
1664
-     * to indicate that it should NOT be cleared from the Registry cache
1665
-     *
1666
-     * @param      $object
1667
-     * @param bool $reset_models
1668
-     * @return bool returns true if cached object should be unset
1669
-     */
1670
-    private static function _reset_and_unset_object($object, $reset_models)
1671
-    {
1672
-        if (! is_object($object)) {
1673
-            // don't unset anything that's not an object
1674
-            return false;
1675
-        }
1676
-        if ($object instanceof EED_Module) {
1677
-            $object::reset();
1678
-            // don't unset modules
1679
-            return false;
1680
-        }
1681
-        if ($object instanceof ResettableInterface) {
1682
-            if ($object instanceof EEM_Base) {
1683
-                if ($reset_models) {
1684
-                    $object->reset();
1685
-                    return true;
1686
-                }
1687
-                return false;
1688
-            }
1689
-            $object->reset();
1690
-            return true;
1691
-        }
1692
-        if (! $object instanceof InterminableInterface) {
1693
-            return true;
1694
-        }
1695
-        return false;
1696
-    }
1697
-
1698
-
1699
-    /**
1700
-     * Gets all the custom post type models defined
1701
-     *
1702
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1703
-     */
1704
-    public function cpt_models()
1705
-    {
1706
-        $cpt_models = array();
1707
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1708
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1709
-                $cpt_models[ $short_name ] = $classname;
1710
-            }
1711
-        }
1712
-        return $cpt_models;
1713
-    }
1714
-
1715
-
1716
-    /**
1717
-     * @return \EE_Config
1718
-     */
1719
-    public static function CFG()
1720
-    {
1721
-        return self::instance()->CFG;
1722
-    }
1723
-
1724
-
1725
-    /**
1726
-     * @deprecated 4.9.62.p
1727
-     * @param string $class_name
1728
-     * @return ReflectionClass
1729
-     * @throws ReflectionException
1730
-     * @throws InvalidDataTypeException
1731
-     */
1732
-    public function get_ReflectionClass($class_name)
1733
-    {
1734
-        return $this->mirror->getReflectionClass($class_name);
1735
-    }
1736
-
1737
-    private function parameterIsPrimitive(?string $param_class): bool
1738
-    {
1739
-        return in_array(
1740
-            $param_class,
1741
-            [
1742
-                'array',
1743
-                'bool',
1744
-                'float',
1745
-                'int',
1746
-                'string',
1747
-            ]
1748
-        );
1749
-    }
981
+				! $this->object_identifier->hasArguments($object_identifier)
982
+				// but previously cached class with args was found
983
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
984
+			) {
985
+				return $object;
986
+			}
987
+		}
988
+		return null;
989
+	}
990
+
991
+
992
+	/**
993
+	 * removes a cached version of the requested class
994
+	 *
995
+	 * @param string  $class_name
996
+	 * @param boolean $addon
997
+	 * @param array   $arguments
998
+	 * @return boolean
999
+	 */
1000
+	public function clear_cached_class(
1001
+		$class_name,
1002
+		$addon = false,
1003
+		$arguments = array()
1004
+	) {
1005
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
1006
+		// check if class has already been loaded, and return it if it has been
1007
+		if (isset($this->{$class_abbreviation})) {
1008
+			$this->{$class_abbreviation} = null;
1009
+			return true;
1010
+		}
1011
+		$class_name = str_replace('\\', '_', $class_name);
1012
+		if (isset($this->{$class_name})) {
1013
+			$this->{$class_name} = null;
1014
+			return true;
1015
+		}
1016
+		if ($addon && $this->addons->has($class_name)) {
1017
+			$this->addons->remove($class_name);
1018
+			return true;
1019
+		}
1020
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1021
+		if ($this->LIB->has($class_name)) {
1022
+			$this->LIB->remove($class_name);
1023
+			return true;
1024
+		}
1025
+		return false;
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 * _set_cached_class
1031
+	 * attempts to cache the instantiated class locally
1032
+	 * in one of the following places, in the following order:
1033
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1034
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1035
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1036
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1037
+	 *
1038
+	 * @param object $class_obj
1039
+	 * @param string $class_name
1040
+	 * @param string $class_prefix
1041
+	 * @param bool   $from_db
1042
+	 * @param array  $arguments
1043
+	 * @return void
1044
+	 */
1045
+	protected function _set_cached_class(
1046
+		$class_obj,
1047
+		$class_name,
1048
+		$class_prefix = '',
1049
+		$from_db = false,
1050
+		$arguments = array()
1051
+	) {
1052
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1053
+			return;
1054
+		}
1055
+		// return newly instantiated class
1056
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1057
+		if ($class_abbreviation) {
1058
+			$this->{$class_abbreviation} = $class_obj;
1059
+			return;
1060
+		}
1061
+		$class_name = str_replace('\\', '_', $class_name);
1062
+		if (property_exists($this, $class_name)) {
1063
+			$this->{$class_name} = $class_obj;
1064
+			return;
1065
+		}
1066
+		if ($class_prefix === 'addon') {
1067
+			$this->addons->add($class_name, $class_obj);
1068
+			return;
1069
+		}
1070
+		if (! $from_db) {
1071
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1072
+			$this->LIB->add($class_name, $class_obj);
1073
+		}
1074
+	}
1075
+
1076
+
1077
+	/**
1078
+	 * attempts to find a full valid filepath for the requested class.
1079
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1080
+	 * then returns that path if the target file has been found and is readable
1081
+	 *
1082
+	 * @param string $class_name
1083
+	 * @param string $type
1084
+	 * @param array  $file_paths
1085
+	 * @return string | bool
1086
+	 */
1087
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
1088
+	{
1089
+		// make sure $file_paths is an array
1090
+		$file_paths = is_array($file_paths)
1091
+			? $file_paths
1092
+			: array($file_paths);
1093
+		// cycle thru paths
1094
+		foreach ($file_paths as $key => $file_path) {
1095
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1096
+			$file_path = $file_path
1097
+				? str_replace(array('/', '\\'), '/', $file_path)
1098
+				: EE_CLASSES;
1099
+			// prep file type
1100
+			$type = ! empty($type)
1101
+				? trim($type, '.') . '.'
1102
+				: '';
1103
+			// build full file path
1104
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1105
+			// does the file exist and can be read ?
1106
+			if (is_readable($file_paths[ $key ])) {
1107
+				return $file_paths[ $key ];
1108
+			}
1109
+		}
1110
+		return false;
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * basically just performs a require_once()
1116
+	 * but with some error handling
1117
+	 *
1118
+	 * @param  string $path
1119
+	 * @param  string $class_name
1120
+	 * @param  string $type
1121
+	 * @param  array  $file_paths
1122
+	 * @return bool
1123
+	 * @throws EE_Error
1124
+	 * @throws ReflectionException
1125
+	 */
1126
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1127
+	{
1128
+		$this->resolve_legacy_class_parent($class_name);
1129
+		// don't give up! you gotta...
1130
+		try {
1131
+			// does the file exist and can it be read ?
1132
+			if (! $path) {
1133
+				// just in case the file has already been autoloaded,
1134
+				// but discrepancies in the naming schema are preventing it from
1135
+				// being loaded via one of the EE_Registry::load_*() methods,
1136
+				// then let's try one last hail mary before throwing an exception
1137
+				// and call class_exists() again, but with autoloading turned ON
1138
+				if (class_exists($class_name)) {
1139
+					return true;
1140
+				}
1141
+				// so sorry, can't find the file
1142
+				throw new EE_Error(
1143
+					sprintf(
1144
+						esc_html__(
1145
+							'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',
1146
+							'event_espresso'
1147
+						),
1148
+						trim($type, '.'),
1149
+						$class_name,
1150
+						'<br />' . implode(',<br />', $file_paths)
1151
+					)
1152
+				);
1153
+			}
1154
+			// get the file
1155
+			require_once($path);
1156
+			// if the class isn't already declared somewhere
1157
+			if (class_exists($class_name, false) === false) {
1158
+				// so sorry, not a class
1159
+				throw new EE_Error(
1160
+					sprintf(
1161
+						esc_html__(
1162
+							'The %s file %s does not appear to contain the %s Class.',
1163
+							'event_espresso'
1164
+						),
1165
+						$type,
1166
+						$path,
1167
+						$class_name
1168
+					)
1169
+				);
1170
+			}
1171
+		} catch (EE_Error $e) {
1172
+			$e->get_error();
1173
+			return false;
1174
+		}
1175
+		return true;
1176
+	}
1177
+
1178
+
1179
+	/**
1180
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1181
+	 * before their class declaration in order to ensure that the parent class was loaded.
1182
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1183
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1184
+	 *
1185
+	 * @param string $class_name
1186
+	 */
1187
+	protected function resolve_legacy_class_parent($class_name = '')
1188
+	{
1189
+		try {
1190
+			$legacy_parent_class_map = array(
1191
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1192
+			);
1193
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1194
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1195
+			}
1196
+		} catch (Exception $exception) {
1197
+		}
1198
+	}
1199
+
1200
+
1201
+	/**
1202
+	 * _create_object
1203
+	 * Attempts to instantiate the requested class via any of the
1204
+	 * commonly used instantiation methods employed throughout EE.
1205
+	 * The priority for instantiation is as follows:
1206
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1207
+	 *        - model objects via their 'new_instance_from_db' method
1208
+	 *        - model objects via their 'new_instance' method
1209
+	 *        - "singleton" classes" via their 'instance' method
1210
+	 *    - standard instantiable classes via their __constructor
1211
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1212
+	 * then the constructor for the requested class will be examined to determine
1213
+	 * if any dependencies exist, and if they can be injected.
1214
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1215
+	 *
1216
+	 * @param string $class_name
1217
+	 * @param array  $arguments
1218
+	 * @param string $type
1219
+	 * @param bool   $from_db
1220
+	 * @return null|object|bool
1221
+	 * @throws InvalidArgumentException
1222
+	 * @throws InvalidInterfaceException
1223
+	 * @throws EE_Error
1224
+	 * @throws ReflectionException
1225
+	 * @throws InvalidDataTypeException
1226
+	 */
1227
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1228
+	{
1229
+		// create reflection
1230
+		$reflector = $this->mirror->getReflectionClass($class_name);
1231
+		// make sure arguments are an array
1232
+		$arguments = is_array($arguments)
1233
+			? $arguments
1234
+			: array($arguments);
1235
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1236
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1237
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1238
+			? $arguments
1239
+			: array($arguments);
1240
+		// attempt to inject dependencies ?
1241
+		if ($this->_dependency_map->has($class_name)) {
1242
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1243
+		}
1244
+		// instantiate the class if possible
1245
+		if ($reflector->isAbstract()) {
1246
+			// nothing to instantiate, loading file was enough
1247
+			// does not throw an exception so $instantiation_mode is unused
1248
+			// $instantiation_mode = "1) no constructor abstract class";
1249
+			return true;
1250
+		}
1251
+		if (
1252
+			empty($arguments)
1253
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1254
+			&& $reflector->isInstantiable()
1255
+		) {
1256
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1257
+			// $instantiation_mode = "2) no constructor but instantiable";
1258
+			return $reflector->newInstance();
1259
+		}
1260
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1261
+			// $instantiation_mode = "3) new_instance_from_db()";
1262
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1263
+		}
1264
+		if (method_exists($class_name, 'new_instance')) {
1265
+			// $instantiation_mode = "4) new_instance()";
1266
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1267
+		}
1268
+		if (method_exists($class_name, 'instance')) {
1269
+			// $instantiation_mode = "5) instance()";
1270
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1271
+		}
1272
+		if ($reflector->isInstantiable()) {
1273
+			$args_passed_count = count($arguments);
1274
+			$args_required_count = count($this->mirror->getRequiredParameters($class_name));
1275
+			if ($args_passed_count < $args_required_count) {
1276
+				throw new RuntimeException(
1277
+					sprintf(
1278
+						__(
1279
+							'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1280
+							'event_espresso'
1281
+						),
1282
+						$class_name,
1283
+						$args_required_count,
1284
+						$args_passed_count
1285
+					)
1286
+				);
1287
+			}
1288
+			// $instantiation_mode = "6) constructor";
1289
+			return $reflector->newInstanceArgs($arguments);
1290
+		}
1291
+		// heh ? something's not right !
1292
+		throw new EE_Error(
1293
+			sprintf(
1294
+				esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1295
+				$type,
1296
+				$class_name
1297
+			)
1298
+		);
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1304
+	 * @param array $array
1305
+	 * @return bool
1306
+	 */
1307
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1308
+	{
1309
+		return ! empty($array)
1310
+			? array_keys($array) === range(0, count($array) - 1)
1311
+			: true;
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * _resolve_dependencies
1317
+	 * examines the constructor for the requested class to determine
1318
+	 * if any dependencies exist, and if they can be injected.
1319
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1320
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1321
+	 * For example:
1322
+	 *        if attempting to load a class "Foo" with the following constructor:
1323
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1324
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1325
+	 *        but only IF they are NOT already present in the incoming arguments array,
1326
+	 *        and the correct classes can be loaded
1327
+	 *
1328
+	 * @param ReflectionClass $reflector
1329
+	 * @param string          $class_name
1330
+	 * @param array           $arguments
1331
+	 * @return array
1332
+	 * @throws InvalidArgumentException
1333
+	 * @throws InvalidDataTypeException
1334
+	 * @throws InvalidInterfaceException
1335
+	 * @throws ReflectionException
1336
+	 */
1337
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1338
+	{
1339
+		// let's examine the constructor
1340
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1341
+		// whu? huh? nothing?
1342
+		if (! $constructor) {
1343
+			return $arguments;
1344
+		}
1345
+		// get constructor parameters
1346
+		$params = $this->mirror->getParametersFromReflection($reflector);
1347
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1348
+		$argument_keys = array_keys($arguments);
1349
+		// now loop thru all of the constructors expected parameters
1350
+		foreach ($params as $index => $param) {
1351
+			try {
1352
+				// is this a dependency for a specific class ?
1353
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1354
+			} catch (ReflectionException $exception) {
1355
+				// uh-oh... most likely a legacy class that has not been autoloaded
1356
+				// let's try to derive the classname from what we have now
1357
+				// and hope that the property var name is close to the class name
1358
+				$param_class = $param->getName();
1359
+				$param_class = str_replace('_', ' ', $param_class);
1360
+				$param_class = ucwords($param_class);
1361
+				$param_class = str_replace(' ', '_', $param_class);
1362
+			}
1363
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1364
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1365
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1366
+				: $param_class;
1367
+			if (
1368
+				// param is not even a class
1369
+				($param_class === null || $this->parameterIsPrimitive($param_class))
1370
+				// and something already exists in the incoming arguments for this param
1371
+				&& array_key_exists($index, $argument_keys)
1372
+				&& array_key_exists($argument_keys[ $index ], $arguments)
1373
+			) {
1374
+				// so let's skip this argument and move on to the next
1375
+				continue;
1376
+			}
1377
+			if (
1378
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1379
+				$param_class !== null
1380
+				&& isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1381
+				&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1382
+			) {
1383
+				// skip this argument and move on to the next
1384
+				continue;
1385
+			}
1386
+			if (
1387
+				// parameter is type hinted as a class, and should be injected
1388
+				$param_class !== null
1389
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1390
+			) {
1391
+				$arguments = $this->_resolve_dependency(
1392
+					$class_name,
1393
+					$param_class,
1394
+					$arguments,
1395
+					$index
1396
+				);
1397
+			}
1398
+			if (empty($arguments[ $index ])) {
1399
+				$default_value = $this->mirror->getParameterDefaultValue(
1400
+					$param,
1401
+					$class_name,
1402
+					$index
1403
+				);
1404
+				// if there's no default value, and the incoming argument is an array (albeit empty), then use that
1405
+				$arguments[ $index ] = $default_value === null
1406
+								 && isset($arguments[ $index ])
1407
+								 && is_array($arguments[ $index ])
1408
+					? $arguments[ $index ]
1409
+					: $default_value;
1410
+			}
1411
+		}
1412
+		return $arguments;
1413
+	}
1414
+
1415
+
1416
+	/**
1417
+	 * @param string $class_name
1418
+	 * @param string $param_class
1419
+	 * @param array  $arguments
1420
+	 * @param mixed  $index
1421
+	 * @return array
1422
+	 * @throws InvalidArgumentException
1423
+	 * @throws InvalidInterfaceException
1424
+	 * @throws InvalidDataTypeException
1425
+	 */
1426
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1427
+	{
1428
+		$dependency = null;
1429
+		// should dependency be loaded from cache ?
1430
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1431
+			$class_name,
1432
+			$param_class
1433
+		);
1434
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1435
+		// we might have a dependency...
1436
+		// let's MAYBE try and find it in our cache if that's what's been requested
1437
+		$cached_class = $cache_on
1438
+			? $this->_get_cached_class($param_class)
1439
+			: null;
1440
+		// and grab it if it exists
1441
+		if ($cached_class instanceof $param_class) {
1442
+			$dependency = $cached_class;
1443
+		} elseif ($param_class !== $class_name) {
1444
+			// obtain the loader method from the dependency map
1445
+			$loader = $this->_dependency_map->class_loader($param_class);
1446
+			// is loader a custom closure ?
1447
+			if ($loader instanceof Closure) {
1448
+				$dependency = $loader($arguments);
1449
+			} else {
1450
+				// set the cache on property for the recursive loading call
1451
+				$this->_cache_on = $cache_on;
1452
+				// if not, then let's try and load it via the registry
1453
+				if ($loader && method_exists($this, $loader)) {
1454
+					$dependency = $this->{$loader}($param_class);
1455
+				} else {
1456
+					$dependency = LoaderFactory::getLoader()->load(
1457
+						$param_class,
1458
+						array(),
1459
+						$cache_on
1460
+					);
1461
+				}
1462
+			}
1463
+		}
1464
+		// did we successfully find the correct dependency ?
1465
+		if ($dependency instanceof $param_class) {
1466
+			// then let's inject it into the incoming array of arguments at the correct location
1467
+			$arguments[ $index ] = $dependency;
1468
+		}
1469
+		return $arguments;
1470
+	}
1471
+
1472
+
1473
+	/**
1474
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1475
+	 *
1476
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1477
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1478
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1479
+	 * @param array  $arguments
1480
+	 * @return object
1481
+	 */
1482
+	public static function factory($classname, $arguments = array())
1483
+	{
1484
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1485
+		if ($loader instanceof Closure) {
1486
+			return $loader($arguments);
1487
+		}
1488
+		if (method_exists(self::instance(), $loader)) {
1489
+			return self::instance()->{$loader}($classname, $arguments);
1490
+		}
1491
+		return null;
1492
+	}
1493
+
1494
+
1495
+	/**
1496
+	 * Gets the addon by its class name
1497
+	 *
1498
+	 * @param string $class_name
1499
+	 * @return EE_Addon
1500
+	 */
1501
+	public function getAddon($class_name)
1502
+	{
1503
+		$class_name = str_replace('\\', '_', $class_name);
1504
+		if (isset($this->addons->{$class_name})) {
1505
+			return $this->addons->{$class_name};
1506
+		} else {
1507
+			return null;
1508
+		}
1509
+	}
1510
+
1511
+
1512
+	/**
1513
+	 * removes the addon from the internal cache
1514
+	 *
1515
+	 * @param string $class_name
1516
+	 * @return void
1517
+	 */
1518
+	public function removeAddon($class_name)
1519
+	{
1520
+		$class_name = str_replace('\\', '_', $class_name);
1521
+		$this->addons->remove($class_name);
1522
+	}
1523
+
1524
+
1525
+	/**
1526
+	 * Gets the addon by its name/slug (not classname. For that, just
1527
+	 * use the get_addon() method above
1528
+	 *
1529
+	 * @param string $name
1530
+	 * @return EE_Addon
1531
+	 */
1532
+	public function get_addon_by_name($name)
1533
+	{
1534
+		foreach ($this->addons as $addon) {
1535
+			if ($addon->name() === $name) {
1536
+				return $addon;
1537
+			}
1538
+		}
1539
+		return null;
1540
+	}
1541
+
1542
+
1543
+	/**
1544
+	 * Gets an array of all the registered addons, where the keys are their names.
1545
+	 * (ie, what each returns for their name() function)
1546
+	 * They're already available on EE_Registry::instance()->addons as properties,
1547
+	 * where each property's name is the addon's classname,
1548
+	 * So if you just want to get the addon by classname,
1549
+	 * OR use the get_addon() method above.
1550
+	 * PLEASE  NOTE:
1551
+	 * addons with Fully Qualified Class Names
1552
+	 * have had the namespace separators converted to underscores,
1553
+	 * so a classname like Fully\Qualified\ClassName
1554
+	 * would have been converted to Fully_Qualified_ClassName
1555
+	 *
1556
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1557
+	 */
1558
+	public function get_addons_by_name()
1559
+	{
1560
+		$addons = array();
1561
+		foreach ($this->addons as $addon) {
1562
+			$addons[ $addon->name() ] = $addon;
1563
+		}
1564
+		return $addons;
1565
+	}
1566
+
1567
+
1568
+	/**
1569
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1570
+	 * a stale copy of it around
1571
+	 *
1572
+	 * @param string $model_name
1573
+	 * @return \EEM_Base
1574
+	 * @throws \EE_Error
1575
+	 */
1576
+	public function reset_model($model_name)
1577
+	{
1578
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1579
+			? "EEM_{$model_name}"
1580
+			: $model_name;
1581
+		if (! $this->LIB->has($model_class_name)) {
1582
+			return null;
1583
+		}
1584
+		$model = $this->LIB->get($model_class_name);
1585
+		if (! $model instanceof EEM_Base) {
1586
+			return null;
1587
+		}
1588
+		// get that model reset it and make sure we nuke the old reference to it
1589
+		if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1590
+			$this->LIB->remove($model_class_name);
1591
+			$this->LIB->add($model_class_name, $model->reset());
1592
+		} else {
1593
+			throw new EE_Error(
1594
+				sprintf(
1595
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1596
+					$model_name
1597
+				)
1598
+			);
1599
+		}
1600
+		return $model;
1601
+	}
1602
+
1603
+
1604
+	/**
1605
+	 * Resets the registry.
1606
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1607
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1608
+	 * - $_dependency_map
1609
+	 * - $_class_abbreviations
1610
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1611
+	 * - $REQ:  Still on the same request so no need to change.
1612
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1613
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1614
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1615
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1616
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1617
+	 *             switch or on the restore.
1618
+	 * - $modules
1619
+	 * - $shortcodes
1620
+	 * - $widgets
1621
+	 *
1622
+	 * @param boolean $hard             [deprecated]
1623
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1624
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1625
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1626
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1627
+	 *                                  client
1628
+	 *                                  code instead can just change the model context to a different blog id if
1629
+	 *                                  necessary
1630
+	 * @return EE_Registry
1631
+	 * @throws InvalidInterfaceException
1632
+	 * @throws InvalidDataTypeException
1633
+	 * @throws EE_Error
1634
+	 * @throws ReflectionException
1635
+	 * @throws InvalidArgumentException
1636
+	 */
1637
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
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
+		// messages reset
1648
+		EED_Messages::reset();
1649
+		// handle of objects cached on LIB
1650
+		foreach (array('LIB', 'modules') as $cache) {
1651
+			foreach ($instance->{$cache} as $class_name => $class) {
1652
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1653
+					unset($instance->{$cache}->{$class_name});
1654
+				}
1655
+			}
1656
+		}
1657
+		return $instance;
1658
+	}
1659
+
1660
+
1661
+	/**
1662
+	 * if passed object implements ResettableInterface, then call it's reset() method
1663
+	 * if passed object implements InterminableInterface, then return false,
1664
+	 * to indicate that it should NOT be cleared from the Registry cache
1665
+	 *
1666
+	 * @param      $object
1667
+	 * @param bool $reset_models
1668
+	 * @return bool returns true if cached object should be unset
1669
+	 */
1670
+	private static function _reset_and_unset_object($object, $reset_models)
1671
+	{
1672
+		if (! is_object($object)) {
1673
+			// don't unset anything that's not an object
1674
+			return false;
1675
+		}
1676
+		if ($object instanceof EED_Module) {
1677
+			$object::reset();
1678
+			// don't unset modules
1679
+			return false;
1680
+		}
1681
+		if ($object instanceof ResettableInterface) {
1682
+			if ($object instanceof EEM_Base) {
1683
+				if ($reset_models) {
1684
+					$object->reset();
1685
+					return true;
1686
+				}
1687
+				return false;
1688
+			}
1689
+			$object->reset();
1690
+			return true;
1691
+		}
1692
+		if (! $object instanceof InterminableInterface) {
1693
+			return true;
1694
+		}
1695
+		return false;
1696
+	}
1697
+
1698
+
1699
+	/**
1700
+	 * Gets all the custom post type models defined
1701
+	 *
1702
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1703
+	 */
1704
+	public function cpt_models()
1705
+	{
1706
+		$cpt_models = array();
1707
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1708
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1709
+				$cpt_models[ $short_name ] = $classname;
1710
+			}
1711
+		}
1712
+		return $cpt_models;
1713
+	}
1714
+
1715
+
1716
+	/**
1717
+	 * @return \EE_Config
1718
+	 */
1719
+	public static function CFG()
1720
+	{
1721
+		return self::instance()->CFG;
1722
+	}
1723
+
1724
+
1725
+	/**
1726
+	 * @deprecated 4.9.62.p
1727
+	 * @param string $class_name
1728
+	 * @return ReflectionClass
1729
+	 * @throws ReflectionException
1730
+	 * @throws InvalidDataTypeException
1731
+	 */
1732
+	public function get_ReflectionClass($class_name)
1733
+	{
1734
+		return $this->mirror->getReflectionClass($class_name);
1735
+	}
1736
+
1737
+	private function parameterIsPrimitive(?string $param_class): bool
1738
+	{
1739
+		return in_array(
1740
+			$param_class,
1741
+			[
1742
+				'array',
1743
+				'bool',
1744
+				'float',
1745
+				'int',
1746
+				'string',
1747
+			]
1748
+		);
1749
+	}
1750 1750
 }
Please login to merge, or discard this patch.