Completed
Branch dev (87b37c)
by
unknown
30:49 queued 23:44
created
core/admin/EE_Admin_Hooks.core.php 1 patch
Indentation   +763 added lines, -763 removed lines patch added patch discarded remove patch
@@ -14,767 +14,767 @@
 block discarded – undo
14 14
  */
15 15
 abstract class EE_Admin_Hooks extends EE_Base
16 16
 {
17
-    /**
18
-     * we're just going to use this to hold the name of the caller class (child class name)
19
-     *
20
-     * @var string
21
-     */
22
-    public $caller;
23
-
24
-
25
-    /**
26
-     * this is just a flag set automatically to indicate whether we've got an extended hook class running (i.e.
27
-     * espresso_events_Registration_Form_Hooks_Extend extends espresso_events_Registration_Form_Hooks).  This flag is
28
-     * used later to make sure we require the needed files.
29
-     *
30
-     * @var bool
31
-     */
32
-    protected $_extend;
33
-
34
-
35
-    /**
36
-     * child classes MUST set this property so that the page object can be loaded correctly
37
-     *
38
-     * @var string
39
-     */
40
-    protected $_name;
41
-
42
-
43
-    /**
44
-     * This is set by child classes and is an associative array of ajax hooks in the format:
45
-     * array(
46
-     *    'ajax_action_ref' => 'executing_method'; //must be public
47
-     * )
48
-     *
49
-     * @var array
50
-     */
51
-    protected $_ajax_func;
52
-
53
-
54
-    /**
55
-     * This is an array of methods that get executed on a page routes admin_init hook. Use the following format:
56
-     * array(
57
-     *    'page_route' => 'executing_method' //must be public
58
-     * )
59
-     *
60
-     * @var array
61
-     */
62
-    protected $_init_func;
63
-
64
-
65
-    /**
66
-     * This is an array of methods that output metabox content for the given page route.  Use the following format:
67
-     * [
68
-     *      0 => [
69
-     *          'page_route' => 'string_for_page_route',    must correspond to a page route in the class being connected
70
-     *                                                      with (i.e. "edit_event") If this is in an array then the
71
-     *                                                      same params below will be used but the metabox will be
72
-     *                                                      added to each route.
73
-     *          'func' =>  'executing_method',              must be public (i.e. public function executing_method
74
-     *                                                      ($post, $callback_args){} ).
75
-     *                                                      Note if you include callback args in the array then you
76
-     *                                                      need to declare them in the method arguments.
77
-     *          'id' => 'identifier_for_metabox',           so it can be removed by addons
78
-     *                                                      (optional, class will set it automatically)
79
-     *          'priority' => 'default',                    default 'default' (optional)
80
-     *          'label' => esc_html__('Localized Title', 'event_espresso'),
81
-     *          'context' => 'advanced'                     advanced is default (optional),
82
-     *      ]
83
-     *      'callback_args' => array() //any callback args to include (optional)
84
-     * ]
85
-     * Why are we indexing numerically?  Because it's possible there may be more than one metabox per page_route.
86
-     *
87
-     * @var array
88
-     */
89
-    protected $_metaboxes;
90
-
91
-
92
-    /**
93
-     * This is an array of values that indicate any metaboxes we want removed from a given page route.  Usually this is
94
-     * used when caffeinated functionality is replacing decaffeinated functionality.  Use the following format for the
95
-     * array: array(
96
-     *    0 => array(
97
-     *        'page_route' => 'string_for_page_route' //can be string or array of strings that match a page_route(s)
98
-     *        that are in the class being connected with (i.e. 'edit', or 'create_new').
99
-     *        'id' => 'identifier_for_metabox', //what the id is of the metabox being removed
100
-     *        'context' => 'normal', //the context for the metabox being removed (has to match)
101
-     *        'screen' => 'screen_id', //(optional), if not included then this class will attempt to remove the metabox
102
-     *        using the currently loaded screen object->id  however, there may be cases where you have to specify the
103
-     *        id for the screen the metabox is on.
104
-     *    )
105
-     * )
106
-     *
107
-     * @var array
108
-     */
109
-    protected $_remove_metaboxes;
110
-
111
-
112
-    /**
113
-     * This parent class takes care of loading the scripts and styles if the child class has set the properties for
114
-     * them in the following format.  Note, the first array index ('register') is for defining all the registers.  The
115
-     * second array index is for indicating what routes each script/style loads on. array(
116
-     * 'registers' => array(
117
-     *        'script_ref' => array( // if more than one script is to be loaded its best to use the 'dependency'
118
-     *        argument to link scripts together.
119
-     *            'type' => 'js' // 'js' or 'css' (defaults to js).  This tells us what type of wp_function to use
120
-     *            'url' => 'http://urltoscript.css.js',
121
-     *            'depends' => array('jquery'), //an array of dependencies for the scripts. REMEMBER, if a script has
122
-     *            already been registered elsewhere in the system.  You can just use the depends array to make sure it
123
-     *            gets loaded before the one you are setting here.
124
-     *            'footer' => TRUE //defaults to true (styles don't use this parameter)
125
-     *        ),
126
-     *    'enqueues' => array( //this time each key corresponds to the script ref followed by an array of page routes
127
-     *    the script gets enqueued on.
128
-     *        'script_ref' => array('route_one', 'route_two')
129
-     *    ),
130
-     *    'localize' => array( //this allows you to set a localized object.  Indicate which script the object is being
131
-     *    attached to and then include an array indexed by the name of the object and the array of key/value pairs for
132
-     *    the object.
133
-     *        'scrip_ref' => array(
134
-     *            'NAME_OF_JS_OBJECT' => array(
135
-     *                'translate_ref' => esc_html__('localized_string', 'event_espresso'),
136
-     *                'some_data' => 5
137
-     *            )
138
-     *        )
139
-     *    )
140
-     * )
141
-     *
142
-     * @var array
143
-     */
144
-    protected $_scripts_styles;
145
-
146
-
147
-    /**
148
-     * This is a property that will contain the current route.
149
-     *
150
-     * @var string;
151
-     */
152
-    protected $_current_route;
153
-
154
-
155
-    /**
156
-     * this optional property can be set by child classes to override the priority for the automatic action/filter hook
157
-     * loading in the `_load_routed_hooks()` method.  Please follow this format: array(
158
-     *    'wp_hook_reference' => 1
159
-     *    )
160
-     * )
161
-     *
162
-     * @var array
163
-     */
164
-    protected $_wp_action_filters_priority;
165
-
166
-
167
-    /**
168
-     * This just holds a merged array of the request vars
169
-     *
170
-     * @var array
171
-     */
172
-    protected $_req_data;
173
-
174
-    /**
175
-     * @var array
176
-     */
177
-    protected $_scripts;
178
-
179
-    /**
180
-     * @var array
181
-     */
182
-    protected $_styles;
183
-
184
-    /**
185
-     * This just holds an instance of the page object for this hook
186
-     *
187
-     * @var EE_Admin_Page
188
-     */
189
-    protected $_page_object;
190
-
191
-
192
-    /**
193
-     * This holds the EE_Admin_Page object from the calling admin page that this object hooks into.
194
-     *
195
-     * @var EE_Admin_Page|EE_Admin_Page_CPT
196
-     */
197
-    protected $_adminpage_obj;
198
-
199
-
200
-    /**
201
-     * Holds EE_Registry object
202
-     *
203
-     * @var EE_Registry
204
-     */
205
-    protected $EE = null;
206
-
207
-    /**
208
-     * @var RequestInterface
209
-     */
210
-    protected $request;
211
-
212
-
213
-    /**
214
-     * constructor
215
-     *
216
-     * @param EE_Admin_Page $admin_page
217
-     * @throws EE_Error
218
-     */
219
-    public function __construct(EE_Admin_Page $admin_page)
220
-    {
221
-        $this->_adminpage_obj = $admin_page;
222
-        $this->request        = LoaderFactory::getLoader()->getShared(RequestInterface::class);
223
-        $this->_req_data      = $this->request->requestParams();
224
-        $page = $this->request->getRequestParam('page');
225
-        $current_page = $this->request->getRequestParam('current_page', $page);
226
-        // first let's verify we're on the right page
227
-        if ($current_page !== $this->_adminpage_obj->page_slug) {
228
-            return;
229
-        }
230
-        $this->_set_defaults();
231
-        $this->_set_hooks_properties();
232
-        // get out nothing more to be done here.
233
-        // allow for extends to modify properties
234
-        if (method_exists($this, '_extend_properties')) {
235
-            $this->_extend_properties();
236
-        }
237
-        $this->_set_page_object();
238
-        $this->_init_hooks();
239
-        $this->_load_custom_methods();
240
-        $this->_load_routed_hooks();
241
-        add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts_styles']);
242
-        add_action('admin_enqueue_scripts', [$this, 'add_metaboxes'], 20);
243
-        add_action('admin_enqueue_scripts', [$this, 'remove_metaboxes'], 15);
244
-        $this->_ajax_hooks();
245
-    }
246
-
247
-
248
-    /**
249
-     * used by child classes to set the following properties:
250
-     * $_ajax_func (optional)
251
-     * $_init_func (optional)
252
-     * $_metaboxes (optional)
253
-     * $_scripts (optional)
254
-     * $_styles (optional)
255
-     * $_name (required)
256
-     * Also in this method will be registered any scripts or styles loaded on the targeted page (as indicated in the
257
-     * _scripts/_styles properties) Also children should place in this method any filters/actions that have to happen
258
-     * really early on page load (just after admin_init) if they want to have them registered for handling early.
259
-     *
260
-     * @abstract
261
-     * @return void
262
-     */
263
-    abstract protected function _set_hooks_properties();
264
-
265
-
266
-    /**
267
-     * The hooks for enqueue_scripts and enqueue_styles will be run in here.  Child classes need to define their
268
-     * scripts and styles in the relevant $_scripts and $_styles properties.  Child classes must have also already
269
-     * registered the scripts and styles using wp_register_script and wp_register_style functions.
270
-     *
271
-     * @return void
272
-     * @throws EE_Error
273
-     */
274
-    public function enqueue_scripts_styles()
275
-    {
276
-        if (! empty($this->_scripts_styles)) {
277
-            // first let's do all the registrations
278
-            if (! isset($this->_scripts_styles['registers'])) {
279
-                $msg[] = esc_html__(
280
-                    'There is no "registers" index in the <code>$this->_scripts_styles</code> property.',
281
-                    'event_espresso'
282
-                );
283
-                $msg[] = sprintf(
284
-                    esc_html__(
285
-                        'Make sure you read the phpdoc comments above the definition of the $_scripts_styles property in the <code>EE_Admin_Hooks</code> class and modify according in the %s child',
286
-                        'event_espresso'
287
-                    ),
288
-                    '<strong>' . $this->caller . '</strong>'
289
-                );
290
-                throw new EE_Error(implode('||', $msg));
291
-            }
292
-            $defaults = [
293
-                'type'    => 'js',
294
-                'url'     => '',
295
-                'depends' => [],
296
-                'version' => EVENT_ESPRESSO_VERSION,
297
-                'footer'  => true,
298
-            ];
299
-            foreach ($this->_scripts_styles['registers'] as $ref => $details) {
300
-                $details = wp_parse_args($details, $defaults);
301
-                $type    = $details['type'];
302
-                $url     = $details['url'];
303
-                $depends = $details['depends'];
304
-                $version = $details['version'];
305
-                $footer  = $details['footer'];
306
-                // let's make sure that we set the 'registers' type if it's not set!
307
-                // We need it later to determine which enqueue we do
308
-                $this->_scripts_styles['registers'][ $ref ]['type'] = $type;
309
-                // let's make sure we're not missing any REQUIRED parameters
310
-                if (empty($url)) {
311
-                    $msg[] = sprintf(
312
-                        esc_html__('Missing the url for the requested %s', 'event_espresso'),
313
-                        $type == 'js' ? 'script' : 'stylesheet'
314
-                    );
315
-                    $msg[] = sprintf(
316
-                        esc_html__(
317
-                            'Doublecheck your <code>$this->_scripts_styles</code> array in %s and make sure that there is a "url" set for the %s ref',
318
-                            'event_espresso'
319
-                        ),
320
-                        '<strong>' . $this->caller . '</strong>',
321
-                        $ref
322
-                    );
323
-                    throw new EE_Error(implode('||', $msg));
324
-                }
325
-                // made it here so let's do the appropriate registration
326
-                $type == 'js'
327
-                    ? wp_register_script($ref, $url, $depends, $version, $footer)
328
-                    : wp_register_style(
329
-                        $ref,
330
-                        $url,
331
-                        $depends,
332
-                        $version
333
-                    );
334
-            }
335
-            // k now let's do the enqueues
336
-            if (! isset($this->_scripts_styles['enqueues'])) {
337
-                return;
338
-            }  //not sure if we should throw an error here or not.
339
-
340
-            foreach ($this->_scripts_styles['enqueues'] as $ref => $routes) {
341
-                // make sure $routes is an array
342
-                $routes = (array) $routes;
343
-                if (in_array($this->_current_route, $routes)) {
344
-                    $this->_scripts_styles['registers'][ $ref ]['type'] == 'js' ? wp_enqueue_script($ref)
345
-                        : wp_enqueue_style($ref);
346
-                    // if we have a localization for the script let's do that too.
347
-                    if (isset($this->_scripts_styles['localize'][ $ref ])) {
348
-                        foreach ($this->_scripts_styles['localize'][ $ref ] as $object_name => $indexes) {
349
-                            wp_localize_script(
350
-                                $ref,
351
-                                $object_name,
352
-                                $this->_scripts_styles['localize'][ $ref ][ $object_name ]
353
-                            );
354
-                        }
355
-                    }
356
-                }
357
-            }
358
-            // let's do the deregisters
359
-            if (! isset($this->_scripts_styles['deregisters'])) {
360
-                return;
361
-            }
362
-            foreach ($this->_scripts_styles['deregisters'] as $ref => $details) {
363
-                $defaults = ['type' => 'js'];
364
-                $details  = wp_parse_args($details, $defaults);
365
-                $details['type'] === 'js' ? wp_deregister_script($ref) : wp_deregister_style($ref);
366
-            }
367
-        }
368
-    }
369
-
370
-
371
-    /**
372
-     * just set the defaults for the hooks properties.
373
-     *
374
-     * @return void
375
-     */
376
-    private function _set_defaults()
377
-    {
378
-        $this->_ajax_func                  = [];
379
-        $this->_init_func                  = [];
380
-        $this->_metaboxes                  = [];
381
-        $this->_scripts                    = [];
382
-        $this->_styles                     = [];
383
-        $this->_wp_action_filters_priority = [];
384
-        $this->_current_route              = $this->getCurrentRoute();
385
-        $this->caller                      = get_class($this);
386
-        $this->_extend                     = (bool) stripos($this->caller, 'Extend');
387
-    }
388
-
389
-
390
-    /**
391
-     * A helper for determining the current route.
392
-     *
393
-     * @return string
394
-     */
395
-    private function getCurrentRoute()
396
-    {
397
-        $action = $this->request->getRequestParam('action');
398
-        // list tables do something else with 'action' for bulk actions.
399
-        $action = $action !== '-1' && $action !== '' ? $action : 'default';
400
-        $route  = $this->request->getRequestParam('route');
401
-        // we set a 'route' variable in some cases where action is being used by something else.
402
-        return $action === 'default' && $route !== '' ? $route : $action;
403
-    }
404
-
405
-
406
-    /**
407
-     * this sets the _page_object property
408
-     *
409
-     * @return void
410
-     * @throws EE_Error
411
-     */
412
-    protected function _set_page_object()
413
-    {
414
-        if ($this->_page_object instanceof EE_Admin_Page) {
415
-            return;
416
-        }
417
-        // first make sure $this->_name is set
418
-        if (empty($this->_name)) {
419
-            $msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
420
-            $msg[] = sprintf(
421
-                esc_html__("This is because the %s child class has not set the '_name' property", 'event_espresso'),
422
-                $this->caller
423
-            );
424
-            throw new EE_Error(implode('||', $msg));
425
-        }
426
-        // change "the_message" to "the message"
427
-        $class_name = str_replace('_', ' ', $this->_name);
428
-        // change "the message" to "The_Message_Admin_Page"
429
-        $class_name = str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
430
-        // first default file (if exists)
431
-        $decaf_file = EE_ADMIN_PAGES . $this->_name . '/' . $class_name . '.core.php';
432
-        if (is_readable($decaf_file)) {
433
-            require_once($decaf_file);
434
-        }
435
-        // now we have to do require for extended file (if needed)
436
-        if ($this->_extend) {
437
-            require_once(EE_CORE_CAF_ADMIN_EXTEND . $this->_name . '/Extend_' . $class_name . '.core.php');
438
-            // and extend the class name as well
439
-            $class_name = 'Extend_' . $class_name;
440
-        }
441
-        // let's make sure the class exists
442
-        if (! class_exists($class_name)) {
443
-            $msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
444
-            $msg[] = sprintf(
445
-                esc_html__(
446
-                    'The class name that was given is %s. Check the spelling and make sure its correct, also there needs to be an autoloader setup for the class',
447
-                    'event_espresso'
448
-                ),
449
-                $class_name
450
-            );
451
-            throw new EE_Error(implode('||', $msg));
452
-        }
453
-        $this->_page_object = LoaderFactory::getLoader()->getShared($class_name, [false]);
454
-        $this->_page_object->initializePage();
455
-    }
456
-
457
-
458
-    /**
459
-     * Child "hook" classes can declare any methods that they want executed when a specific page route is loaded.  The
460
-     * advantage of this is when doing things like running our own db interactions on saves etc.  Remember that
461
-     * $this->_req_data (all the _POST and _GET data) is available to your methods.
462
-     *
463
-     * @return void
464
-     */
465
-    private function _load_custom_methods()
466
-    {
467
-        /**
468
-         * method cannot be named 'default' (@see http://us3.php
469
-         * .net/manual/en/reserved.keywords.php) so need to
470
-         * handle routes that are "default"
471
-         *
472
-         * @since 4.3.0
473
-         */
474
-        $method_callback = $this->_current_route == 'default' ? 'default_callback' : $this->_current_route;
475
-        // these run before the Admin_Page route executes.
476
-        if (method_exists($this, $method_callback)) {
477
-            call_user_func([$this, $method_callback]);
478
-        }
479
-        // these run via the _redirect_after_action method in EE_Admin_Page which usually happens after non_UI methods in EE_Admin_Page classes.  There are two redirect actions, the first fires before $query_args might be manipulated by "save and close" actions and the seond fires right before the actual redirect happens.
480
-        // first the actions
481
-        // note that these action hooks will have the $query_args value available.
482
-        $admin_class_name = get_class($this->_adminpage_obj);
483
-        if (method_exists($this, '_redirect_action_early_' . $this->_current_route)) {
484
-            add_action(
485
-                'AHEE__'
486
-                . $admin_class_name
487
-                . '___redirect_after_action__before_redirect_modification_'
488
-                . $this->_current_route,
489
-                [$this, '_redirect_action_early_' . $this->_current_route],
490
-                10
491
-            );
492
-        }
493
-        if (method_exists($this, '_redirect_action_' . $this->_current_route)) {
494
-            add_action(
495
-                'AHEE_redirect_' . $admin_class_name . $this->_current_route,
496
-                [$this, '_redirect_action_' . $this->_current_route],
497
-                10
498
-            );
499
-        }
500
-        // let's hook into the _redirect itself and allow for changing where the user goes after redirect.  This will have $query_args and $redirect_url available.
501
-        if (method_exists($this, '_redirect_filter_' . $this->_current_route)) {
502
-            add_filter(
503
-                'FHEE_redirect_' . $admin_class_name . $this->_current_route,
504
-                [$this, '_redirect_filter_' . $this->_current_route],
505
-                10,
506
-                2
507
-            );
508
-        }
509
-    }
510
-
511
-
512
-    /**
513
-     * This method will search for a corresponding method with a name matching the route and the wp_hook to run.  This
514
-     * allows child hook classes to target hooking into a specific wp action or filter hook ONLY on a certain route.
515
-     * just remember, methods MUST be public Future hooks should be added in here to be access by child classes.
516
-     *
517
-     * @return void
518
-     */
519
-    private function _load_routed_hooks()
520
-    {
521
-
522
-        // this array provides the hook action names that will be referenced.  Key is the action. Value is an array with the type (action or filter) and the number of parameters for the hook.  We'll default all priorities for automatic hooks to 10.
523
-        $hook_filter_array = [
524
-            'admin_footer'                                                                            => [
525
-                'type'     => 'action',
526
-                'argnum'   => 1,
527
-                'priority' => 10,
528
-            ],
529
-            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug . '_' . $this->_current_route => [
530
-                'type'     => 'filter',
531
-                'argnum'   => 1,
532
-                'priority' => 10,
533
-            ],
534
-            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug                               => [
535
-                'type'     => 'filter',
536
-                'argnum'   => 1,
537
-                'priority' => 10,
538
-            ],
539
-            'FHEE_list_table_views'                                                                   => [
540
-                'type'     => 'filter',
541
-                'argnum'   => 1,
542
-                'priority' => 10,
543
-            ],
544
-            'AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes'                              => [
545
-                'type'     => 'action',
546
-                'argnum'   => 1,
547
-                'priority' => 10,
548
-            ],
549
-        ];
550
-        foreach ($hook_filter_array as $hook => $args) {
551
-            if (method_exists($this, $this->_current_route . '_' . $hook)) {
552
-                if (isset($this->_wp_action_filters_priority[ $hook ])) {
553
-                    $args['priority'] = $this->_wp_action_filters_priority[ $hook ];
554
-                }
555
-                if ($args['type'] == 'action') {
556
-                    add_action(
557
-                        $hook,
558
-                        [$this, $this->_current_route . '_' . $hook],
559
-                        $args['priority'],
560
-                        $args['argnum']
561
-                    );
562
-                } else {
563
-                    add_filter(
564
-                        $hook,
565
-                        [$this, $this->_current_route . '_' . $hook],
566
-                        $args['priority'],
567
-                        $args['argnum']
568
-                    );
569
-                }
570
-            }
571
-        }
572
-    }
573
-
574
-
575
-    /**
576
-     * Loop throught the $_ajax_func array and add_actions for the array.
577
-     *
578
-     * @return void
579
-     * @throws EE_Error
580
-     */
581
-    private function _ajax_hooks()
582
-    {
583
-        if (empty($this->_ajax_func)) {
584
-            return;
585
-        } //get out there's nothing to take care of.
586
-        foreach ($this->_ajax_func as $action => $method) {
587
-            // make sure method exists
588
-            if (! method_exists($this, $method)) {
589
-                $msg[] = esc_html__(
590
-                    'There is no corresponding method for the hook labeled in the _ajax_func array',
591
-                    'event_espresso'
592
-                ) . '<br />';
593
-                $msg[] = sprintf(
594
-                    esc_html__(
595
-                        'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
596
-                        'event_espresso'
597
-                    ),
598
-                    $method,
599
-                    $this->caller
600
-                );
601
-                throw new EE_Error(implode('||', $msg));
602
-            }
603
-            add_action('wp_ajax_' . $action, [$this, $method]);
604
-        }
605
-    }
606
-
607
-
608
-    /**
609
-     * Loop throught the $_init_func array and add_actions for the array.
610
-     *
611
-     * @return void
612
-     * @throws EE_Error
613
-     */
614
-    protected function _init_hooks()
615
-    {
616
-        if (empty($this->_init_func)) {
617
-            return;
618
-        }
619
-        // get out there's nothing to take care of.
620
-        // We need to determine what page_route we are on!
621
-        foreach ($this->_init_func as $route => $method) {
622
-            // make sure method exists
623
-            if (! method_exists($this, $method)) {
624
-                $msg[] = esc_html__(
625
-                    'There is no corresponding method for the hook labeled in the _init_func array',
626
-                    'event_espresso'
627
-                ) . '<br />';
628
-                $msg[] = sprintf(
629
-                    esc_html__(
630
-                        'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
631
-                        'event_espresso'
632
-                    ),
633
-                    $method,
634
-                    $this->caller
635
-                );
636
-                throw new EE_Error(implode('||', $msg));
637
-            }
638
-            if ($route == $this->_current_route) {
639
-                add_action('admin_init', [$this, $method]);
640
-            }
641
-        }
642
-    }
643
-
644
-
645
-    /**
646
-     * Loop through the _metaboxes property and add_metaboxes accordingly
647
-     * //todo we could eventually make this a config component class (i.e. new EE_Metabox);
648
-     *
649
-     * @return void
650
-     * @throws EE_Error
651
-     */
652
-    public function add_metaboxes()
653
-    {
654
-        if (empty($this->_metaboxes)) {
655
-            return;
656
-        } //get out we don't have any metaboxes to set for this connection
657
-        $this->_handle_metabox_array($this->_metaboxes);
658
-    }
659
-
660
-
661
-    /**
662
-     * @param array $boxes
663
-     * @param bool  $add
664
-     * @throws EE_Error
665
-     */
666
-    private function _handle_metabox_array(array $boxes, $add = true)
667
-    {
668
-        foreach ($boxes as $box) {
669
-            if (! isset($box['page_route'])) {
670
-                continue;
671
-            }
672
-            // we don't have a valid array
673
-            // let's make sure $box['page_route'] is an array so the "foreach" will work.
674
-            $box['page_route'] = (array) $box['page_route'];
675
-            foreach ($box['page_route'] as $route) {
676
-                if ($route != $this->_current_route) {
677
-                    continue;
678
-                } //get out we only add metaboxes for set route.
679
-                if ($add) {
680
-                    $this->_add_metabox($box);
681
-                } else {
682
-                    $this->_remove_metabox($box);
683
-                }
684
-            }
685
-        }
686
-    }
687
-
688
-
689
-    /**
690
-     * Loop through the _remove_metaboxes property and remove metaboxes accordingly.
691
-     *
692
-     * @return void
693
-     * @throws EE_Error
694
-     */
695
-    public function remove_metaboxes()
696
-    {
697
-        if (empty($this->_remove_metaboxes)) {
698
-            return;
699
-        } //get out there are no metaboxes to remove
700
-        $this->_handle_metabox_array($this->_remove_metaboxes, false);
701
-    }
702
-
703
-
704
-    /**
705
-     * This just handles adding a metabox
706
-     *
707
-     * @param array $args an array of args that have been set for this metabox by the child class
708
-     * @throws EE_Error
709
-     */
710
-    private function _add_metabox($args)
711
-    {
712
-        $current_screen = get_current_screen();
713
-        $screen_id      = is_object($current_screen) ? $current_screen->id : null;
714
-        $func           = isset($args['func']) ? $args['func'] : 'some_invalid_callback';
715
-        // set defaults
716
-        $defaults      = [
717
-            'callback_args' => [],
718
-            'context'       => 'advanced',
719
-            'func'          => $func,
720
-            'id'            => $this->caller . '_' . $func . '_metabox',
721
-            'label'         => $this->caller,
722
-            'page'          => isset($args['page']) ? $args['page'] : $screen_id,
723
-            'priority'      => 'default',
724
-        ];
725
-        $args          = wp_parse_args($args, $defaults);
726
-        $callback_args = $args['callback_args'];
727
-        $context       = $args['context'];
728
-        $func          = $args['func'];
729
-        $id            = $args['id'];
730
-        $label         = $args['label'];
731
-        $page          = $args['page'];
732
-        $priority      = $args['priority'];
733
-        // make sure method exists
734
-        if (! method_exists($this, $func)) {
735
-            $msg[] =
736
-                esc_html__('There is no corresponding method to display the metabox content', 'event_espresso')
737
-                . '<br />';
738
-            $msg[] = sprintf(
739
-                esc_html__(
740
-                    'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
741
-                    'event_espresso'
742
-                ),
743
-                $func,
744
-                $this->caller
745
-            );
746
-            throw new EE_Error(implode('||', $msg));
747
-        }
748
-        // everything checks out so let's add the metabox
749
-        add_meta_box($id, $label, [$this, $func], $page, $context, $priority, $callback_args);
750
-        add_filter(
751
-            "postbox_classes_{$page}_{$id}",
752
-            function ($classes) {
753
-                array_push($classes, 'ee-admin-container');
754
-                return $classes;
755
-            }
756
-        );
757
-    }
758
-
759
-
760
-    private function _remove_metabox($args)
761
-    {
762
-        $current_screen = get_current_screen();
763
-        $screen_id      = is_object($current_screen) ? $current_screen->id : null;
764
-        $func           = isset($args['func']) ? $args['func'] : 'some_invalid_callback';
765
-        // set defaults
766
-        $defaults = [
767
-            'context' => 'default',
768
-            'id'      => isset($args['id'])
769
-                ? $args['id']
770
-                : $this->_current_route . '_' . $this->caller . '_' . $func . '_metabox',
771
-            'screen'  => isset($args['screen']) ? $args['screen'] : $screen_id,
772
-        ];
773
-        $args     = wp_parse_args($args, $defaults);
774
-        $context  = $args['context'];
775
-        $id       = $args['id'];
776
-        $screen   = $args['screen'];
777
-        // everything checks out so lets remove the box!
778
-        remove_meta_box($id, $screen, $context);
779
-    }
17
+	/**
18
+	 * we're just going to use this to hold the name of the caller class (child class name)
19
+	 *
20
+	 * @var string
21
+	 */
22
+	public $caller;
23
+
24
+
25
+	/**
26
+	 * this is just a flag set automatically to indicate whether we've got an extended hook class running (i.e.
27
+	 * espresso_events_Registration_Form_Hooks_Extend extends espresso_events_Registration_Form_Hooks).  This flag is
28
+	 * used later to make sure we require the needed files.
29
+	 *
30
+	 * @var bool
31
+	 */
32
+	protected $_extend;
33
+
34
+
35
+	/**
36
+	 * child classes MUST set this property so that the page object can be loaded correctly
37
+	 *
38
+	 * @var string
39
+	 */
40
+	protected $_name;
41
+
42
+
43
+	/**
44
+	 * This is set by child classes and is an associative array of ajax hooks in the format:
45
+	 * array(
46
+	 *    'ajax_action_ref' => 'executing_method'; //must be public
47
+	 * )
48
+	 *
49
+	 * @var array
50
+	 */
51
+	protected $_ajax_func;
52
+
53
+
54
+	/**
55
+	 * This is an array of methods that get executed on a page routes admin_init hook. Use the following format:
56
+	 * array(
57
+	 *    'page_route' => 'executing_method' //must be public
58
+	 * )
59
+	 *
60
+	 * @var array
61
+	 */
62
+	protected $_init_func;
63
+
64
+
65
+	/**
66
+	 * This is an array of methods that output metabox content for the given page route.  Use the following format:
67
+	 * [
68
+	 *      0 => [
69
+	 *          'page_route' => 'string_for_page_route',    must correspond to a page route in the class being connected
70
+	 *                                                      with (i.e. "edit_event") If this is in an array then the
71
+	 *                                                      same params below will be used but the metabox will be
72
+	 *                                                      added to each route.
73
+	 *          'func' =>  'executing_method',              must be public (i.e. public function executing_method
74
+	 *                                                      ($post, $callback_args){} ).
75
+	 *                                                      Note if you include callback args in the array then you
76
+	 *                                                      need to declare them in the method arguments.
77
+	 *          'id' => 'identifier_for_metabox',           so it can be removed by addons
78
+	 *                                                      (optional, class will set it automatically)
79
+	 *          'priority' => 'default',                    default 'default' (optional)
80
+	 *          'label' => esc_html__('Localized Title', 'event_espresso'),
81
+	 *          'context' => 'advanced'                     advanced is default (optional),
82
+	 *      ]
83
+	 *      'callback_args' => array() //any callback args to include (optional)
84
+	 * ]
85
+	 * Why are we indexing numerically?  Because it's possible there may be more than one metabox per page_route.
86
+	 *
87
+	 * @var array
88
+	 */
89
+	protected $_metaboxes;
90
+
91
+
92
+	/**
93
+	 * This is an array of values that indicate any metaboxes we want removed from a given page route.  Usually this is
94
+	 * used when caffeinated functionality is replacing decaffeinated functionality.  Use the following format for the
95
+	 * array: array(
96
+	 *    0 => array(
97
+	 *        'page_route' => 'string_for_page_route' //can be string or array of strings that match a page_route(s)
98
+	 *        that are in the class being connected with (i.e. 'edit', or 'create_new').
99
+	 *        'id' => 'identifier_for_metabox', //what the id is of the metabox being removed
100
+	 *        'context' => 'normal', //the context for the metabox being removed (has to match)
101
+	 *        'screen' => 'screen_id', //(optional), if not included then this class will attempt to remove the metabox
102
+	 *        using the currently loaded screen object->id  however, there may be cases where you have to specify the
103
+	 *        id for the screen the metabox is on.
104
+	 *    )
105
+	 * )
106
+	 *
107
+	 * @var array
108
+	 */
109
+	protected $_remove_metaboxes;
110
+
111
+
112
+	/**
113
+	 * This parent class takes care of loading the scripts and styles if the child class has set the properties for
114
+	 * them in the following format.  Note, the first array index ('register') is for defining all the registers.  The
115
+	 * second array index is for indicating what routes each script/style loads on. array(
116
+	 * 'registers' => array(
117
+	 *        'script_ref' => array( // if more than one script is to be loaded its best to use the 'dependency'
118
+	 *        argument to link scripts together.
119
+	 *            'type' => 'js' // 'js' or 'css' (defaults to js).  This tells us what type of wp_function to use
120
+	 *            'url' => 'http://urltoscript.css.js',
121
+	 *            'depends' => array('jquery'), //an array of dependencies for the scripts. REMEMBER, if a script has
122
+	 *            already been registered elsewhere in the system.  You can just use the depends array to make sure it
123
+	 *            gets loaded before the one you are setting here.
124
+	 *            'footer' => TRUE //defaults to true (styles don't use this parameter)
125
+	 *        ),
126
+	 *    'enqueues' => array( //this time each key corresponds to the script ref followed by an array of page routes
127
+	 *    the script gets enqueued on.
128
+	 *        'script_ref' => array('route_one', 'route_two')
129
+	 *    ),
130
+	 *    'localize' => array( //this allows you to set a localized object.  Indicate which script the object is being
131
+	 *    attached to and then include an array indexed by the name of the object and the array of key/value pairs for
132
+	 *    the object.
133
+	 *        'scrip_ref' => array(
134
+	 *            'NAME_OF_JS_OBJECT' => array(
135
+	 *                'translate_ref' => esc_html__('localized_string', 'event_espresso'),
136
+	 *                'some_data' => 5
137
+	 *            )
138
+	 *        )
139
+	 *    )
140
+	 * )
141
+	 *
142
+	 * @var array
143
+	 */
144
+	protected $_scripts_styles;
145
+
146
+
147
+	/**
148
+	 * This is a property that will contain the current route.
149
+	 *
150
+	 * @var string;
151
+	 */
152
+	protected $_current_route;
153
+
154
+
155
+	/**
156
+	 * this optional property can be set by child classes to override the priority for the automatic action/filter hook
157
+	 * loading in the `_load_routed_hooks()` method.  Please follow this format: array(
158
+	 *    'wp_hook_reference' => 1
159
+	 *    )
160
+	 * )
161
+	 *
162
+	 * @var array
163
+	 */
164
+	protected $_wp_action_filters_priority;
165
+
166
+
167
+	/**
168
+	 * This just holds a merged array of the request vars
169
+	 *
170
+	 * @var array
171
+	 */
172
+	protected $_req_data;
173
+
174
+	/**
175
+	 * @var array
176
+	 */
177
+	protected $_scripts;
178
+
179
+	/**
180
+	 * @var array
181
+	 */
182
+	protected $_styles;
183
+
184
+	/**
185
+	 * This just holds an instance of the page object for this hook
186
+	 *
187
+	 * @var EE_Admin_Page
188
+	 */
189
+	protected $_page_object;
190
+
191
+
192
+	/**
193
+	 * This holds the EE_Admin_Page object from the calling admin page that this object hooks into.
194
+	 *
195
+	 * @var EE_Admin_Page|EE_Admin_Page_CPT
196
+	 */
197
+	protected $_adminpage_obj;
198
+
199
+
200
+	/**
201
+	 * Holds EE_Registry object
202
+	 *
203
+	 * @var EE_Registry
204
+	 */
205
+	protected $EE = null;
206
+
207
+	/**
208
+	 * @var RequestInterface
209
+	 */
210
+	protected $request;
211
+
212
+
213
+	/**
214
+	 * constructor
215
+	 *
216
+	 * @param EE_Admin_Page $admin_page
217
+	 * @throws EE_Error
218
+	 */
219
+	public function __construct(EE_Admin_Page $admin_page)
220
+	{
221
+		$this->_adminpage_obj = $admin_page;
222
+		$this->request        = LoaderFactory::getLoader()->getShared(RequestInterface::class);
223
+		$this->_req_data      = $this->request->requestParams();
224
+		$page = $this->request->getRequestParam('page');
225
+		$current_page = $this->request->getRequestParam('current_page', $page);
226
+		// first let's verify we're on the right page
227
+		if ($current_page !== $this->_adminpage_obj->page_slug) {
228
+			return;
229
+		}
230
+		$this->_set_defaults();
231
+		$this->_set_hooks_properties();
232
+		// get out nothing more to be done here.
233
+		// allow for extends to modify properties
234
+		if (method_exists($this, '_extend_properties')) {
235
+			$this->_extend_properties();
236
+		}
237
+		$this->_set_page_object();
238
+		$this->_init_hooks();
239
+		$this->_load_custom_methods();
240
+		$this->_load_routed_hooks();
241
+		add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts_styles']);
242
+		add_action('admin_enqueue_scripts', [$this, 'add_metaboxes'], 20);
243
+		add_action('admin_enqueue_scripts', [$this, 'remove_metaboxes'], 15);
244
+		$this->_ajax_hooks();
245
+	}
246
+
247
+
248
+	/**
249
+	 * used by child classes to set the following properties:
250
+	 * $_ajax_func (optional)
251
+	 * $_init_func (optional)
252
+	 * $_metaboxes (optional)
253
+	 * $_scripts (optional)
254
+	 * $_styles (optional)
255
+	 * $_name (required)
256
+	 * Also in this method will be registered any scripts or styles loaded on the targeted page (as indicated in the
257
+	 * _scripts/_styles properties) Also children should place in this method any filters/actions that have to happen
258
+	 * really early on page load (just after admin_init) if they want to have them registered for handling early.
259
+	 *
260
+	 * @abstract
261
+	 * @return void
262
+	 */
263
+	abstract protected function _set_hooks_properties();
264
+
265
+
266
+	/**
267
+	 * The hooks for enqueue_scripts and enqueue_styles will be run in here.  Child classes need to define their
268
+	 * scripts and styles in the relevant $_scripts and $_styles properties.  Child classes must have also already
269
+	 * registered the scripts and styles using wp_register_script and wp_register_style functions.
270
+	 *
271
+	 * @return void
272
+	 * @throws EE_Error
273
+	 */
274
+	public function enqueue_scripts_styles()
275
+	{
276
+		if (! empty($this->_scripts_styles)) {
277
+			// first let's do all the registrations
278
+			if (! isset($this->_scripts_styles['registers'])) {
279
+				$msg[] = esc_html__(
280
+					'There is no "registers" index in the <code>$this->_scripts_styles</code> property.',
281
+					'event_espresso'
282
+				);
283
+				$msg[] = sprintf(
284
+					esc_html__(
285
+						'Make sure you read the phpdoc comments above the definition of the $_scripts_styles property in the <code>EE_Admin_Hooks</code> class and modify according in the %s child',
286
+						'event_espresso'
287
+					),
288
+					'<strong>' . $this->caller . '</strong>'
289
+				);
290
+				throw new EE_Error(implode('||', $msg));
291
+			}
292
+			$defaults = [
293
+				'type'    => 'js',
294
+				'url'     => '',
295
+				'depends' => [],
296
+				'version' => EVENT_ESPRESSO_VERSION,
297
+				'footer'  => true,
298
+			];
299
+			foreach ($this->_scripts_styles['registers'] as $ref => $details) {
300
+				$details = wp_parse_args($details, $defaults);
301
+				$type    = $details['type'];
302
+				$url     = $details['url'];
303
+				$depends = $details['depends'];
304
+				$version = $details['version'];
305
+				$footer  = $details['footer'];
306
+				// let's make sure that we set the 'registers' type if it's not set!
307
+				// We need it later to determine which enqueue we do
308
+				$this->_scripts_styles['registers'][ $ref ]['type'] = $type;
309
+				// let's make sure we're not missing any REQUIRED parameters
310
+				if (empty($url)) {
311
+					$msg[] = sprintf(
312
+						esc_html__('Missing the url for the requested %s', 'event_espresso'),
313
+						$type == 'js' ? 'script' : 'stylesheet'
314
+					);
315
+					$msg[] = sprintf(
316
+						esc_html__(
317
+							'Doublecheck your <code>$this->_scripts_styles</code> array in %s and make sure that there is a "url" set for the %s ref',
318
+							'event_espresso'
319
+						),
320
+						'<strong>' . $this->caller . '</strong>',
321
+						$ref
322
+					);
323
+					throw new EE_Error(implode('||', $msg));
324
+				}
325
+				// made it here so let's do the appropriate registration
326
+				$type == 'js'
327
+					? wp_register_script($ref, $url, $depends, $version, $footer)
328
+					: wp_register_style(
329
+						$ref,
330
+						$url,
331
+						$depends,
332
+						$version
333
+					);
334
+			}
335
+			// k now let's do the enqueues
336
+			if (! isset($this->_scripts_styles['enqueues'])) {
337
+				return;
338
+			}  //not sure if we should throw an error here or not.
339
+
340
+			foreach ($this->_scripts_styles['enqueues'] as $ref => $routes) {
341
+				// make sure $routes is an array
342
+				$routes = (array) $routes;
343
+				if (in_array($this->_current_route, $routes)) {
344
+					$this->_scripts_styles['registers'][ $ref ]['type'] == 'js' ? wp_enqueue_script($ref)
345
+						: wp_enqueue_style($ref);
346
+					// if we have a localization for the script let's do that too.
347
+					if (isset($this->_scripts_styles['localize'][ $ref ])) {
348
+						foreach ($this->_scripts_styles['localize'][ $ref ] as $object_name => $indexes) {
349
+							wp_localize_script(
350
+								$ref,
351
+								$object_name,
352
+								$this->_scripts_styles['localize'][ $ref ][ $object_name ]
353
+							);
354
+						}
355
+					}
356
+				}
357
+			}
358
+			// let's do the deregisters
359
+			if (! isset($this->_scripts_styles['deregisters'])) {
360
+				return;
361
+			}
362
+			foreach ($this->_scripts_styles['deregisters'] as $ref => $details) {
363
+				$defaults = ['type' => 'js'];
364
+				$details  = wp_parse_args($details, $defaults);
365
+				$details['type'] === 'js' ? wp_deregister_script($ref) : wp_deregister_style($ref);
366
+			}
367
+		}
368
+	}
369
+
370
+
371
+	/**
372
+	 * just set the defaults for the hooks properties.
373
+	 *
374
+	 * @return void
375
+	 */
376
+	private function _set_defaults()
377
+	{
378
+		$this->_ajax_func                  = [];
379
+		$this->_init_func                  = [];
380
+		$this->_metaboxes                  = [];
381
+		$this->_scripts                    = [];
382
+		$this->_styles                     = [];
383
+		$this->_wp_action_filters_priority = [];
384
+		$this->_current_route              = $this->getCurrentRoute();
385
+		$this->caller                      = get_class($this);
386
+		$this->_extend                     = (bool) stripos($this->caller, 'Extend');
387
+	}
388
+
389
+
390
+	/**
391
+	 * A helper for determining the current route.
392
+	 *
393
+	 * @return string
394
+	 */
395
+	private function getCurrentRoute()
396
+	{
397
+		$action = $this->request->getRequestParam('action');
398
+		// list tables do something else with 'action' for bulk actions.
399
+		$action = $action !== '-1' && $action !== '' ? $action : 'default';
400
+		$route  = $this->request->getRequestParam('route');
401
+		// we set a 'route' variable in some cases where action is being used by something else.
402
+		return $action === 'default' && $route !== '' ? $route : $action;
403
+	}
404
+
405
+
406
+	/**
407
+	 * this sets the _page_object property
408
+	 *
409
+	 * @return void
410
+	 * @throws EE_Error
411
+	 */
412
+	protected function _set_page_object()
413
+	{
414
+		if ($this->_page_object instanceof EE_Admin_Page) {
415
+			return;
416
+		}
417
+		// first make sure $this->_name is set
418
+		if (empty($this->_name)) {
419
+			$msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
420
+			$msg[] = sprintf(
421
+				esc_html__("This is because the %s child class has not set the '_name' property", 'event_espresso'),
422
+				$this->caller
423
+			);
424
+			throw new EE_Error(implode('||', $msg));
425
+		}
426
+		// change "the_message" to "the message"
427
+		$class_name = str_replace('_', ' ', $this->_name);
428
+		// change "the message" to "The_Message_Admin_Page"
429
+		$class_name = str_replace(' ', '_', ucwords($class_name)) . '_Admin_Page';
430
+		// first default file (if exists)
431
+		$decaf_file = EE_ADMIN_PAGES . $this->_name . '/' . $class_name . '.core.php';
432
+		if (is_readable($decaf_file)) {
433
+			require_once($decaf_file);
434
+		}
435
+		// now we have to do require for extended file (if needed)
436
+		if ($this->_extend) {
437
+			require_once(EE_CORE_CAF_ADMIN_EXTEND . $this->_name . '/Extend_' . $class_name . '.core.php');
438
+			// and extend the class name as well
439
+			$class_name = 'Extend_' . $class_name;
440
+		}
441
+		// let's make sure the class exists
442
+		if (! class_exists($class_name)) {
443
+			$msg[] = esc_html__('We can\'t load the page object', 'event_espresso');
444
+			$msg[] = sprintf(
445
+				esc_html__(
446
+					'The class name that was given is %s. Check the spelling and make sure its correct, also there needs to be an autoloader setup for the class',
447
+					'event_espresso'
448
+				),
449
+				$class_name
450
+			);
451
+			throw new EE_Error(implode('||', $msg));
452
+		}
453
+		$this->_page_object = LoaderFactory::getLoader()->getShared($class_name, [false]);
454
+		$this->_page_object->initializePage();
455
+	}
456
+
457
+
458
+	/**
459
+	 * Child "hook" classes can declare any methods that they want executed when a specific page route is loaded.  The
460
+	 * advantage of this is when doing things like running our own db interactions on saves etc.  Remember that
461
+	 * $this->_req_data (all the _POST and _GET data) is available to your methods.
462
+	 *
463
+	 * @return void
464
+	 */
465
+	private function _load_custom_methods()
466
+	{
467
+		/**
468
+		 * method cannot be named 'default' (@see http://us3.php
469
+		 * .net/manual/en/reserved.keywords.php) so need to
470
+		 * handle routes that are "default"
471
+		 *
472
+		 * @since 4.3.0
473
+		 */
474
+		$method_callback = $this->_current_route == 'default' ? 'default_callback' : $this->_current_route;
475
+		// these run before the Admin_Page route executes.
476
+		if (method_exists($this, $method_callback)) {
477
+			call_user_func([$this, $method_callback]);
478
+		}
479
+		// these run via the _redirect_after_action method in EE_Admin_Page which usually happens after non_UI methods in EE_Admin_Page classes.  There are two redirect actions, the first fires before $query_args might be manipulated by "save and close" actions and the seond fires right before the actual redirect happens.
480
+		// first the actions
481
+		// note that these action hooks will have the $query_args value available.
482
+		$admin_class_name = get_class($this->_adminpage_obj);
483
+		if (method_exists($this, '_redirect_action_early_' . $this->_current_route)) {
484
+			add_action(
485
+				'AHEE__'
486
+				. $admin_class_name
487
+				. '___redirect_after_action__before_redirect_modification_'
488
+				. $this->_current_route,
489
+				[$this, '_redirect_action_early_' . $this->_current_route],
490
+				10
491
+			);
492
+		}
493
+		if (method_exists($this, '_redirect_action_' . $this->_current_route)) {
494
+			add_action(
495
+				'AHEE_redirect_' . $admin_class_name . $this->_current_route,
496
+				[$this, '_redirect_action_' . $this->_current_route],
497
+				10
498
+			);
499
+		}
500
+		// let's hook into the _redirect itself and allow for changing where the user goes after redirect.  This will have $query_args and $redirect_url available.
501
+		if (method_exists($this, '_redirect_filter_' . $this->_current_route)) {
502
+			add_filter(
503
+				'FHEE_redirect_' . $admin_class_name . $this->_current_route,
504
+				[$this, '_redirect_filter_' . $this->_current_route],
505
+				10,
506
+				2
507
+			);
508
+		}
509
+	}
510
+
511
+
512
+	/**
513
+	 * This method will search for a corresponding method with a name matching the route and the wp_hook to run.  This
514
+	 * allows child hook classes to target hooking into a specific wp action or filter hook ONLY on a certain route.
515
+	 * just remember, methods MUST be public Future hooks should be added in here to be access by child classes.
516
+	 *
517
+	 * @return void
518
+	 */
519
+	private function _load_routed_hooks()
520
+	{
521
+
522
+		// this array provides the hook action names that will be referenced.  Key is the action. Value is an array with the type (action or filter) and the number of parameters for the hook.  We'll default all priorities for automatic hooks to 10.
523
+		$hook_filter_array = [
524
+			'admin_footer'                                                                            => [
525
+				'type'     => 'action',
526
+				'argnum'   => 1,
527
+				'priority' => 10,
528
+			],
529
+			'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug . '_' . $this->_current_route => [
530
+				'type'     => 'filter',
531
+				'argnum'   => 1,
532
+				'priority' => 10,
533
+			],
534
+			'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug                               => [
535
+				'type'     => 'filter',
536
+				'argnum'   => 1,
537
+				'priority' => 10,
538
+			],
539
+			'FHEE_list_table_views'                                                                   => [
540
+				'type'     => 'filter',
541
+				'argnum'   => 1,
542
+				'priority' => 10,
543
+			],
544
+			'AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes'                              => [
545
+				'type'     => 'action',
546
+				'argnum'   => 1,
547
+				'priority' => 10,
548
+			],
549
+		];
550
+		foreach ($hook_filter_array as $hook => $args) {
551
+			if (method_exists($this, $this->_current_route . '_' . $hook)) {
552
+				if (isset($this->_wp_action_filters_priority[ $hook ])) {
553
+					$args['priority'] = $this->_wp_action_filters_priority[ $hook ];
554
+				}
555
+				if ($args['type'] == 'action') {
556
+					add_action(
557
+						$hook,
558
+						[$this, $this->_current_route . '_' . $hook],
559
+						$args['priority'],
560
+						$args['argnum']
561
+					);
562
+				} else {
563
+					add_filter(
564
+						$hook,
565
+						[$this, $this->_current_route . '_' . $hook],
566
+						$args['priority'],
567
+						$args['argnum']
568
+					);
569
+				}
570
+			}
571
+		}
572
+	}
573
+
574
+
575
+	/**
576
+	 * Loop throught the $_ajax_func array and add_actions for the array.
577
+	 *
578
+	 * @return void
579
+	 * @throws EE_Error
580
+	 */
581
+	private function _ajax_hooks()
582
+	{
583
+		if (empty($this->_ajax_func)) {
584
+			return;
585
+		} //get out there's nothing to take care of.
586
+		foreach ($this->_ajax_func as $action => $method) {
587
+			// make sure method exists
588
+			if (! method_exists($this, $method)) {
589
+				$msg[] = esc_html__(
590
+					'There is no corresponding method for the hook labeled in the _ajax_func array',
591
+					'event_espresso'
592
+				) . '<br />';
593
+				$msg[] = sprintf(
594
+					esc_html__(
595
+						'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
596
+						'event_espresso'
597
+					),
598
+					$method,
599
+					$this->caller
600
+				);
601
+				throw new EE_Error(implode('||', $msg));
602
+			}
603
+			add_action('wp_ajax_' . $action, [$this, $method]);
604
+		}
605
+	}
606
+
607
+
608
+	/**
609
+	 * Loop throught the $_init_func array and add_actions for the array.
610
+	 *
611
+	 * @return void
612
+	 * @throws EE_Error
613
+	 */
614
+	protected function _init_hooks()
615
+	{
616
+		if (empty($this->_init_func)) {
617
+			return;
618
+		}
619
+		// get out there's nothing to take care of.
620
+		// We need to determine what page_route we are on!
621
+		foreach ($this->_init_func as $route => $method) {
622
+			// make sure method exists
623
+			if (! method_exists($this, $method)) {
624
+				$msg[] = esc_html__(
625
+					'There is no corresponding method for the hook labeled in the _init_func array',
626
+					'event_espresso'
627
+				) . '<br />';
628
+				$msg[] = sprintf(
629
+					esc_html__(
630
+						'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
631
+						'event_espresso'
632
+					),
633
+					$method,
634
+					$this->caller
635
+				);
636
+				throw new EE_Error(implode('||', $msg));
637
+			}
638
+			if ($route == $this->_current_route) {
639
+				add_action('admin_init', [$this, $method]);
640
+			}
641
+		}
642
+	}
643
+
644
+
645
+	/**
646
+	 * Loop through the _metaboxes property and add_metaboxes accordingly
647
+	 * //todo we could eventually make this a config component class (i.e. new EE_Metabox);
648
+	 *
649
+	 * @return void
650
+	 * @throws EE_Error
651
+	 */
652
+	public function add_metaboxes()
653
+	{
654
+		if (empty($this->_metaboxes)) {
655
+			return;
656
+		} //get out we don't have any metaboxes to set for this connection
657
+		$this->_handle_metabox_array($this->_metaboxes);
658
+	}
659
+
660
+
661
+	/**
662
+	 * @param array $boxes
663
+	 * @param bool  $add
664
+	 * @throws EE_Error
665
+	 */
666
+	private function _handle_metabox_array(array $boxes, $add = true)
667
+	{
668
+		foreach ($boxes as $box) {
669
+			if (! isset($box['page_route'])) {
670
+				continue;
671
+			}
672
+			// we don't have a valid array
673
+			// let's make sure $box['page_route'] is an array so the "foreach" will work.
674
+			$box['page_route'] = (array) $box['page_route'];
675
+			foreach ($box['page_route'] as $route) {
676
+				if ($route != $this->_current_route) {
677
+					continue;
678
+				} //get out we only add metaboxes for set route.
679
+				if ($add) {
680
+					$this->_add_metabox($box);
681
+				} else {
682
+					$this->_remove_metabox($box);
683
+				}
684
+			}
685
+		}
686
+	}
687
+
688
+
689
+	/**
690
+	 * Loop through the _remove_metaboxes property and remove metaboxes accordingly.
691
+	 *
692
+	 * @return void
693
+	 * @throws EE_Error
694
+	 */
695
+	public function remove_metaboxes()
696
+	{
697
+		if (empty($this->_remove_metaboxes)) {
698
+			return;
699
+		} //get out there are no metaboxes to remove
700
+		$this->_handle_metabox_array($this->_remove_metaboxes, false);
701
+	}
702
+
703
+
704
+	/**
705
+	 * This just handles adding a metabox
706
+	 *
707
+	 * @param array $args an array of args that have been set for this metabox by the child class
708
+	 * @throws EE_Error
709
+	 */
710
+	private function _add_metabox($args)
711
+	{
712
+		$current_screen = get_current_screen();
713
+		$screen_id      = is_object($current_screen) ? $current_screen->id : null;
714
+		$func           = isset($args['func']) ? $args['func'] : 'some_invalid_callback';
715
+		// set defaults
716
+		$defaults      = [
717
+			'callback_args' => [],
718
+			'context'       => 'advanced',
719
+			'func'          => $func,
720
+			'id'            => $this->caller . '_' . $func . '_metabox',
721
+			'label'         => $this->caller,
722
+			'page'          => isset($args['page']) ? $args['page'] : $screen_id,
723
+			'priority'      => 'default',
724
+		];
725
+		$args          = wp_parse_args($args, $defaults);
726
+		$callback_args = $args['callback_args'];
727
+		$context       = $args['context'];
728
+		$func          = $args['func'];
729
+		$id            = $args['id'];
730
+		$label         = $args['label'];
731
+		$page          = $args['page'];
732
+		$priority      = $args['priority'];
733
+		// make sure method exists
734
+		if (! method_exists($this, $func)) {
735
+			$msg[] =
736
+				esc_html__('There is no corresponding method to display the metabox content', 'event_espresso')
737
+				. '<br />';
738
+			$msg[] = sprintf(
739
+				esc_html__(
740
+					'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
741
+					'event_espresso'
742
+				),
743
+				$func,
744
+				$this->caller
745
+			);
746
+			throw new EE_Error(implode('||', $msg));
747
+		}
748
+		// everything checks out so let's add the metabox
749
+		add_meta_box($id, $label, [$this, $func], $page, $context, $priority, $callback_args);
750
+		add_filter(
751
+			"postbox_classes_{$page}_{$id}",
752
+			function ($classes) {
753
+				array_push($classes, 'ee-admin-container');
754
+				return $classes;
755
+			}
756
+		);
757
+	}
758
+
759
+
760
+	private function _remove_metabox($args)
761
+	{
762
+		$current_screen = get_current_screen();
763
+		$screen_id      = is_object($current_screen) ? $current_screen->id : null;
764
+		$func           = isset($args['func']) ? $args['func'] : 'some_invalid_callback';
765
+		// set defaults
766
+		$defaults = [
767
+			'context' => 'default',
768
+			'id'      => isset($args['id'])
769
+				? $args['id']
770
+				: $this->_current_route . '_' . $this->caller . '_' . $func . '_metabox',
771
+			'screen'  => isset($args['screen']) ? $args['screen'] : $screen_id,
772
+		];
773
+		$args     = wp_parse_args($args, $defaults);
774
+		$context  = $args['context'];
775
+		$id       = $args['id'];
776
+		$screen   = $args['screen'];
777
+		// everything checks out so lets remove the box!
778
+		remove_meta_box($id, $screen, $context);
779
+	}
780 780
 }
Please login to merge, or discard this patch.