Completed
Branch BUG/batch-strings-overridden (415991)
by
unknown
09:29 queued 38s
created

EE_Admin_Hooks   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 723
Duplicated Lines 2.77 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 20
loc 723
rs 2.277
c 0
b 0
f 0
wmc 75
lcom 1
cbo 3

15 Methods

Rating   Name   Duplication   Size   Complexity  
_set_hooks_properties() 0 1 ?
A __construct() 0 27 5
D enqueue_scripts_styles() 0 94 16
A _set_defaults() 0 7 2
A getCurrentRoute() 0 8 5
B _set_page_object() 0 39 6
B _load_custom_methods() 0 45 6
B _load_routed_hooks() 0 54 5
A _ajax_hooks() 10 26 4
B _init_hooks() 10 29 6
A add_metaboxes() 0 7 2
B _handle_metabox_array() 0 21 6
A remove_metaboxes() 0 8 2
A _add_metabox() 0 33 5
A _remove_metabox() 0 23 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EE_Admin_Hooks often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EE_Admin_Hooks, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * EE_Admin_Hooks
5
 * This is the abstract parent class used by children to contains any hooks that run on different EE Admin pages.
6
 * @abstract
7
 * @package         EE_Admin_Hooks
8
 * @subpackage      includes/core/admin/EE_Admin_Hooks.class.php
9
 * @author          Darren Ethier
10
 * ------------------------------------------------------------------------
11
 */
12
abstract class EE_Admin_Hooks extends EE_Base
13
{
14
15
16
    /**
17
     * we're just going to use this to hold the name of the caller class (child class name)
18
     *
19
     * @var string
20
     */
21
    public $caller;
22
23
24
    /**
25
     * this is just a flag set automatically to indicate whether we've got an extended hook class running (i.e.
26
     * espresso_events_Registration_Form_Hooks_Extend extends espresso_events_Registration_Form_Hooks).  This flag is
27
     * used later to make sure we require the needed files.
28
     *
29
     * @var bool
30
     */
31
    protected $_extend;
32
33
34
    /**
35
     * child classes MUST set this property so that the page object can be loaded correctly
36
     *
37
     * @var string
38
     */
39
    protected $_name;
40
41
42
    /**
43
     * This is set by child classes and is an associative array of ajax hooks in the format:
44
     * array(
45
     *    'ajax_action_ref' => 'executing_method'; //must be public
46
     * )
47
     *
48
     * @var array
49
     */
50
    protected $_ajax_func;
51
52
53
    /**
54
     * This is an array of methods that get executed on a page routes admin_init hook. Use the following format:
55
     * array(
56
     *    'page_route' => 'executing_method' //must be public
57
     * )
58
     *
59
     * @var array
60
     */
61
    protected $_init_func;
62
63
64
    /**
65
     * This is an array of methods that output metabox content for the given page route.  Use the following format:
66
     * array(
67
     *    0 => array(
68
     *        'page_route' => 'string_for_page_route', //must correspond to a page route in the class being connected
69
     *        with (i.e. "edit_event") If this is in an array then the same params below will be used but the metabox
70
     *        will be added to each route.
71
     *        'func' =>  'executing_method',  //must be public (i.e. public function executing_method($post,
72
     *        $callback_args){} ).  Note if you include callback args in the array then you need to declare them in the
73
     *        method arguments.
74
     *        'id' => 'identifier_for_metabox', //so it can be removed by addons (optional, class will set it
75
     *        automatically)
76
     *        'priority' => 'default', //default 'default' (optional)
77
     *        'label' => __('Localized Title', 'event_espresso'),
78
     *        'context' => 'advanced' //advanced is default (optional),
79
     *    'callback_args' => array() //any callback args to include (optional)
80
     * )
81
     * Why are we indexing numerically?  Because it's possible there may be more than one metabox per page_route.
82
     *
83
     * @var array
84
     */
85
    protected $_metaboxes;
86
87
88
    /**
89
     * This is an array of values that indicate any metaboxes we want removed from a given page route.  Usually this is
90
     * used when caffeinated functionality is replacing decaffeinated functionality.  Use the following format for the
91
     * array: array(
92
     *    0 => array(
93
     *        'page_route' => 'string_for_page_route' //can be string or array of strings that match a page_route(s)
94
     *        that are in the class being connected with (i.e. 'edit', or 'create_new').
95
     *        'id' => 'identifier_for_metabox', //what the id is of the metabox being removed
96
     *        'context' => 'normal', //the context for the metabox being removed (has to match)
97
     *        'screen' => 'screen_id', //(optional), if not included then this class will attempt to remove the metabox
98
     *        using the currently loaded screen object->id  however, there may be cases where you have to specify the
99
     *        id for the screen the metabox is on.
100
     *    )
101
     * )
102
     *
103
     * @var array
104
     */
105
    protected $_remove_metaboxes;
106
107
108
    /**
109
     * This parent class takes care of loading the scripts and styles if the child class has set the properties for
110
     * them in the following format.  Note, the first array index ('register') is for defining all the registers.  The
111
     * second array index is for indicating what routes each script/style loads on. array(
112
     * 'registers' => array(
113
     *        'script_ref' => array( // if more than one script is to be loaded its best to use the 'dependency'
114
     *        argument to link scripts together.
115
     *            'type' => 'js' // 'js' or 'css' (defaults to js).  This tells us what type of wp_function to use
116
     *            'url' => 'http://urltoscript.css.js',
117
     *            'depends' => array('jquery'), //an array of dependencies for the scripts. REMEMBER, if a script has
118
     *            already been registered elsewhere in the system.  You can just use the depends array to make sure it
119
     *            gets loaded before the one you are setting here.
120
     *            'footer' => TRUE //defaults to true (styles don't use this parameter)
121
     *        ),
122
     *    'enqueues' => array( //this time each key corresponds to the script ref followed by an array of page routes
123
     *    the script gets enqueued on.
124
     *        'script_ref' => array('route_one', 'route_two')
125
     *    ),
126
     *    'localize' => array( //this allows you to set a localize object.  Indicate which script the object is being
127
     *    attached to and then include an array indexed by the name of the object and the array of key/value pairs for
128
     *    the object.
129
     *        'scrip_ref' => array(
130
     *            'NAME_OF_JS_OBJECT' => array(
131
     *                'translate_ref' => __('localized_string', 'event_espresso'),
132
     *                'some_data' => 5
133
     *            )
134
     *        )
135
     *    )
136
     * )
137
     *
138
     * @var array
139
     */
140
    protected $_scripts_styles;
141
142
143
    /**
144
     * This is a property that will contain the current route.
145
     *
146
     * @var string;
147
     */
148
    protected $_current_route;
149
150
151
    /**
152
     * this optional property can be set by child classes to override the priority for the automatic action/filter hook
153
     * loading in the `_load_routed_hooks()` method.  Please follow this format: array(
154
     *    'wp_hook_reference' => 1
155
     *    )
156
     * )
157
     *
158
     * @var array
159
     */
160
    protected $_wp_action_filters_priority;
161
162
163
    /**
164
     * This just holds a merged array of the $_POST and $_GET vars in favor of $_POST
165
     *
166
     * @var array
167
     */
168
    protected $_req_data;
169
170
171
    /**
172
     * This just holds an instance of the page object for this hook
173
     *
174
     * @var EE_Admin_Page
175
     */
176
    protected $_page_object;
177
178
179
    /**
180
     * This holds the EE_Admin_Page object from the calling admin page that this object hooks into.
181
     *
182
     * @var EE_Admin_Page|EE_Admin_Page_CPT
183
     */
184
    protected $_adminpage_obj;
185
186
187
    /**
188
     * Holds EE_Registry object
189
     *
190
     * @var EE_Registry
191
     */
192
    protected $EE = null;
193
194
195
    /**
196
     * constructor
197
     *
198
     * @param EE_Admin_Page $admin_page the calling admin_page_object
0 ignored issues
show
Documentation introduced by
There is no parameter named $admin_page. Did you maybe mean $adminpage?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
199
     */
200
    public function __construct(EE_Admin_Page $adminpage)
201
    {
202
203
        $this->_adminpage_obj = $adminpage;
204
        $this->_req_data = array_merge($_GET, $_POST);
205
        $this->_set_defaults();
206
        $this->_set_hooks_properties();
207
        // first let's verify we're on the right page
208
        if (! isset($this->_req_data['page'])
209
            || (isset($this->_req_data['page'])
210
                && $this->_adminpage_obj->page_slug
211
                   != $this->_req_data['page'])) {
212
            return;
213
        } //get out nothing more to be done here.
214
        // allow for extends to modify properties
215
        if (method_exists($this, '_extend_properties')) {
216
            $this->_extend_properties();
217
        }
218
        $this->_set_page_object();
219
        $this->_init_hooks();
220
        $this->_load_custom_methods();
221
        $this->_load_routed_hooks();
222
        add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_styles'));
223
        add_action('admin_enqueue_scripts', array($this, 'add_metaboxes'), 20);
224
        add_action('admin_enqueue_scripts', array($this, 'remove_metaboxes'), 15);
225
        $this->_ajax_hooks();
226
    }
227
228
229
    /**
230
     * used by child classes to set the following properties:
231
     * $_ajax_func (optional)
232
     * $_init_func (optional)
233
     * $_metaboxes (optional)
234
     * $_scripts (optional)
235
     * $_styles (optional)
236
     * $_name (required)
237
     * Also in this method will be registered any scripts or styles loaded on the targeted page (as indicated in the
238
     * _scripts/_styles properties) Also children should place in this method any filters/actions that have to happen
239
     * really early on page load (just after admin_init) if they want to have them registered for handling early.
240
     *
241
     * @access protected
242
     * @abstract
243
     * @return void
244
     */
245
    abstract protected function _set_hooks_properties();
246
247
248
    /**
249
     * The hooks for enqueue_scripts and enqueue_styles will be run in here.  Child classes need to define their
250
     * scripts and styles in the relevant $_scripts and $_styles properties.  Child classes must have also already
251
     * registered the scripts and styles using wp_register_script and wp_register_style functions.
252
     *
253
     * @access public
254
     * @return void
255
     */
256
    public function enqueue_scripts_styles()
257
    {
258
259
        if (! empty($this->_scripts_styles)) {
260
            // first let's do all the registrations
261
            if (! isset($this->_scripts_styles['registers'])) {
262
                $msg[] = __(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$msg was never initialized. Although not strictly required by PHP, it is generally a good practice to add $msg = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
263
                    'There is no "registers" index in the <code>$this->_scripts_styles</code> property.',
264
                    'event_espresso'
265
                );
266
                $msg[] = sprintf(
267
                    __(
268
                        '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',
269
                        'event_espresso'
270
                    ),
271
                    '<strong>' . $this->caller . '</strong>'
272
                );
273
                throw new EE_Error(implode('||', $msg));
274
            }
275
            foreach ($this->_scripts_styles['registers'] as $ref => $details) {
276
                $defaults = array(
277
                    'type'    => 'js',
278
                    'url'     => '',
279
                    'depends' => array(),
280
                    'version' => EVENT_ESPRESSO_VERSION,
281
                    'footer'  => true,
282
                );
283
                $details = wp_parse_args($details, $defaults);
284
                extract($details);
285
                // let's make sure that we set the 'registers' type if it's not set! We need it later to determine whhich enqueu we do
286
                $this->_scripts_styles['registers'][ $ref ]['type'] = $type;
287
                // let's make sure we're not missing any REQUIRED parameters
288
                if (empty($url)) {
289
                    $msg[] = sprintf(
290
                        __('Missing the url for the requested %s', 'event_espresso'),
291
                        $type == 'js' ? 'script' : 'stylesheet'
292
                    );
293
                    $msg[] = sprintf(
294
                        __(
295
                            'Doublecheck your <code>$this->_scripts_styles</code> array in %s and make sure that there is a "url" set for the %s ref',
296
                            'event_espresso'
297
                        ),
298
                        '<strong>' . $this->caller . '</strong>',
299
                        $ref
300
                    );
301
                    throw new EE_Error(implode('||', $msg));
302
                }
303
                // made it here so let's do the appropriate registration
304
                $type == 'js'
305
                    ? wp_register_script($ref, $url, $depends, $version, $footer)
306
                    : wp_register_style(
307
                        $ref,
308
                        $url,
309
                        $depends,
310
                        $version
311
                    );
312
            }
313
            // k now lets do the enqueues
314
            if (! isset($this->_scripts_styles['enqueues'])) {
315
                return;
316
            }  //not sure if we should throw an error here or not.
317
318
            foreach ($this->_scripts_styles['enqueues'] as $ref => $routes) {
319
                // make sure $routes is an array
320
                $routes = (array) $routes;
321
                if (in_array($this->_current_route, $routes)) {
322
                    $this->_scripts_styles['registers'][ $ref ]['type'] == 'js' ? wp_enqueue_script($ref)
323
                        : wp_enqueue_style($ref);
324
                    // if we have a localization for the script let's do that too.
325
                    if (isset($this->_scripts_styles['localize'][ $ref ])) {
326
                        foreach ($this->_scripts_styles['localize'][ $ref ] as $object_name => $indexes) {
327
                            wp_localize_script(
328
                                $ref,
329
                                $object_name,
330
                                $this->_scripts_styles['localize'][ $ref ][ $object_name ]
331
                            );
332
                        }
333
                    }
334
                }
335
            }
336
            // let's do the deregisters
337
            if (! isset($this->_scripts_styles['deregisters'])) {
338
                return;
339
            }
340
            foreach ($this->_scripts_styles['deregisters'] as $ref => $details) {
341
                $defaults = array(
342
                    'type' => 'js',
343
                );
344
                $details = wp_parse_args($details, $defaults);
345
                extract($details);
346
                $type == 'js' ? wp_deregister_script($ref) : wp_deregister_style($ref);
347
            }
348
        }
349
    }
350
351
352
    /**
353
     * just set the defaults for the hooks properties.
354
     *
355
     * @access private
356
     * @return void
357
     */
358
    private function _set_defaults()
359
    {
360
        $this->_ajax_func = $this->_init_func = $this->_metaboxes = $this->_scripts = $this->_styles = $this->_wp_action_filters_priority = array();
0 ignored issues
show
Bug introduced by
The property _scripts does not seem to exist. Did you mean _scripts_styles?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Bug introduced by
The property _styles does not seem to exist. Did you mean _scripts_styles?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
361
        $this->_current_route = $this->getCurrentRoute();
362
        $this->caller = get_class($this);
363
        $this->_extend = stripos($this->caller, 'Extend') ? true : false;
364
    }
365
366
367
    /**
368
     * A helper for determining the current route.
369
     * @return string
370
     */
371
    private function getCurrentRoute()
372
    {
373
        // list tables do something else with 'action' for bulk actions.
374
        $action = ! empty($_REQUEST['action']) && $_REQUEST['action'] !== '-1' ? $_REQUEST['action'] : 'default';
375
        // we set a 'route' variable in some cases where action is being used by something else.
376
        $action = $action === 'default' && isset($_REQUEST['route']) ? $_REQUEST['route'] : $action;
377
        return sanitize_key($action);
378
    }
379
380
381
    /**
382
     * this sets the _page_object property
383
     *
384
     * @access protected
385
     * @return void
386
     */
387
    protected function _set_page_object()
388
    {
389
        // first make sure $this->_name is set
390
        if (empty($this->_name)) {
391
            $msg[] = __('We can\'t load the page object', 'event_espresso');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$msg was never initialized. Although not strictly required by PHP, it is generally a good practice to add $msg = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
392
            $msg[] = sprintf(
393
                __("This is because the %s child class has not set the '_name' property", 'event_espresso'),
394
                $this->caller
395
            );
396
            throw new EE_Error(implode('||', $msg));
397
        }
398
        $ref = str_replace('_', ' ', $this->_name); // take the_message -> the message
399
        $ref = str_replace(' ', '_', ucwords($ref)) . '_Admin_Page'; // take the message -> The_Message
400
        // first default file (if exists)
401
        $decaf_file = EE_ADMIN_PAGES . $this->_name . DS . $ref . '.core.php';
402
        if (is_readable($decaf_file)) {
403
            require_once($decaf_file);
404
        }
405
        // now we have to do require for extended file (if needed)
406
        if ($this->_extend) {
407
            require_once(EE_CORE_CAF_ADMIN_EXTEND . $this->_name . DS . 'Extend_' . $ref . '.core.php');
408
        }
409
        // if we've got an extended class we use that!
410
        $ref = $this->_extend ? 'Extend_' . $ref : $ref;
411
        // let's make sure the class exists
412
        if (! class_exists($ref)) {
413
            $msg[] = __('We can\'t load the page object', 'event_espresso');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$msg was never initialized. Although not strictly required by PHP, it is generally a good practice to add $msg = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
414
            $msg[] = sprintf(
415
                __(
416
                    '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',
417
                    'event_espresso'
418
                ),
419
                $ref
420
            );
421
            throw new EE_Error(implode('||', $msg));
422
        }
423
        $a = new ReflectionClass($ref);
424
        $this->_page_object = $a->newInstance(false);
425
    }
426
427
428
    /**
429
     * Child "hook" classes can declare any methods that they want executed when a specific page route is loaded.  The
430
     * advantage of this is when doing things like running our own db interactions on saves etc.  Remember that
431
     * $this->_req_data (all the _POST and _GET data) is available to your methods.
432
     *
433
     * @access private
434
     * @return void
435
     */
436
    private function _load_custom_methods()
437
    {
438
        /**
439
         * method cannot be named 'default' (@see http://us3.php
440
         * .net/manual/en/reserved.keywords.php) so need to
441
         * handle routes that are "default"
442
         *
443
         * @since 4.3.0
444
         */
445
        $method_callback = $this->_current_route == 'default' ? 'default_callback' : $this->_current_route;
446
        // these run before the Admin_Page route executes.
447
        if (method_exists($this, $method_callback)) {
448
            call_user_func(array($this, $method_callback));
449
        }
450
        // 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.
451
        // first the actions
452
        // note that these action hooks will have the $query_args value available.
453
        $admin_class_name = get_class($this->_adminpage_obj);
454
        if (method_exists($this, '_redirect_action_early_' . $this->_current_route)) {
455
            add_action(
456
                'AHEE__'
457
                . $admin_class_name
458
                . '___redirect_after_action__before_redirect_modification_'
459
                . $this->_current_route,
460
                array($this, '_redirect_action_early_' . $this->_current_route),
461
                10
462
            );
463
        }
464
        if (method_exists($this, '_redirect_action_' . $this->_current_route)) {
465
            add_action(
466
                'AHEE_redirect_' . $admin_class_name . $this->_current_route,
467
                array($this, '_redirect_action_' . $this->_current_route),
468
                10
469
            );
470
        }
471
        // 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.
472
        if (method_exists($this, '_redirect_filter_' . $this->_current_route)) {
473
            add_filter(
474
                'FHEE_redirect_' . $admin_class_name . $this->_current_route,
475
                array($this, '_redirect_filter_' . $this->_current_route),
476
                10,
477
                2
478
            );
479
        }
480
    }
481
482
483
    /**
484
     * This method will search for a corresponding method with a name matching the route and the wp_hook to run.  This
485
     * allows child hook classes to target hooking into a specific wp action or filter hook ONLY on a certain route.
486
     * just remember, methods MUST be public Future hooks should be added in here to be access by child classes.
487
     *
488
     * @return void
489
     */
490
    private function _load_routed_hooks()
491
    {
492
493
        // 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.
494
        $hook_filter_array = array(
495
            'admin_footer'                                                                            => array(
496
                'type'     => 'action',
497
                'argnum'   => 1,
498
                'priority' => 10,
499
            ),
500
            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug . '_' . $this->_current_route => array(
501
                'type'     => 'filter',
502
                'argnum'   => 1,
503
                'priority' => 10,
504
            ),
505
            'FHEE_list_table_views_' . $this->_adminpage_obj->page_slug                               => array(
506
                'type'     => 'filter',
507
                'argnum'   => 1,
508
                'priority' => 10,
509
            ),
510
            'FHEE_list_table_views'                                                                   => array(
511
                'type'     => 'filter',
512
                'argnum'   => 1,
513
                'priority' => 10,
514
            ),
515
            'AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes'                              => array(
516
                'type'     => 'action',
517
                'argnum'   => 1,
518
                'priority' => 10,
519
            ),
520
        );
521
        foreach ($hook_filter_array as $hook => $args) {
522
            if (method_exists($this, $this->_current_route . '_' . $hook)) {
523
                if (isset($this->_wp_action_filters_priority[ $hook ])) {
524
                    $args['priority'] = $this->_wp_action_filters_priority[ $hook ];
525
                }
526
                if ($args['type'] == 'action') {
527
                    add_action(
528
                        $hook,
529
                        array($this, $this->_current_route . '_' . $hook),
530
                        $args['priority'],
531
                        $args['argnum']
532
                    );
533
                } else {
534
                    add_filter(
535
                        $hook,
536
                        array($this, $this->_current_route . '_' . $hook),
537
                        $args['priority'],
538
                        $args['argnum']
539
                    );
540
                }
541
            }
542
        }
543
    }
544
545
546
    /**
547
     * Loop throught the $_ajax_func array and add_actions for the array.
548
     *
549
     * @return void
550
     */
551
    private function _ajax_hooks()
552
    {
553
554
        if (empty($this->_ajax_func)) {
555
            return;
556
        } //get out there's nothing to take care of.
557 View Code Duplication
        foreach ($this->_ajax_func as $action => $method) {
558
            // make sure method exists
559
            if (! method_exists($this, $method)) {
560
                $msg[] = __(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$msg was never initialized. Although not strictly required by PHP, it is generally a good practice to add $msg = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
561
                    'There is no corresponding method for the hook labeled in the _ajax_func array',
562
                    'event_espresso'
563
                ) . '<br />';
564
                $msg[] = sprintf(
565
                    __(
566
                        'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
567
                        'event_espresso'
568
                    ),
569
                    $method,
570
                    $this->caller
571
                );
572
                throw new EE_Error(implode('||', $msg));
573
            }
574
            add_action('wp_ajax_' . $action, array($this, $method));
575
        }
576
    }
577
578
579
    /**
580
     * Loop throught the $_init_func array and add_actions for the array.
581
     *
582
     * @return void
583
     */
584
    protected function _init_hooks()
585
    {
586
        if (empty($this->_init_func)) {
587
            return;
588
        } //get out there's nothing to take care of.
589
        // We need to determine what page_route we are on!
590
        $current_route = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'default';
0 ignored issues
show
Unused Code introduced by
$current_route is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
591 View Code Duplication
        foreach ($this->_init_func as $route => $method) {
592
            // make sure method exists
593
            if (! method_exists($this, $method)) {
594
                $msg[] = __(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$msg was never initialized. Although not strictly required by PHP, it is generally a good practice to add $msg = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
595
                    'There is no corresponding method for the hook labeled in the _init_func array',
596
                    'event_espresso'
597
                ) . '<br />';
598
                $msg[] = sprintf(
599
                    __(
600
                        'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
601
                        'event_espresso'
602
                    ),
603
                    $method,
604
                    $this->caller
605
                );
606
                throw new EE_Error(implode('||', $msg));
607
            }
608
            if ($route == $this->_current_route) {
609
                add_action('admin_init', array($this, $method));
610
            }
611
        }
612
    }
613
614
615
    /**
616
     * Loop through the _metaboxes property and add_metaboxes accordingly
617
     * //todo we could eventually make this a config component class (i.e. new EE_Metabox);
618
     *
619
     * @access public
620
     * @return void
621
     */
622
    public function add_metaboxes()
623
    {
624
        if (empty($this->_metaboxes)) {
625
            return;
626
        } //get out we don't have any metaboxes to set for this connection
627
        $this->_handle_metabox_array($this->_metaboxes);
628
    }
629
630
631
    private function _handle_metabox_array($boxes, $add = true)
632
    {
633
634
        foreach ($boxes as $box) {
635
            if (! isset($box['page_route'])) {
636
                continue;
637
            } //we dont' have a valid array
638
            // let's make sure $box['page_route'] is an array so the "foreach" will work.
639
            $box['page_route'] = (array) $box['page_route'];
640
            foreach ($box['page_route'] as $route) {
641
                if ($route != $this->_current_route) {
642
                    continue;
643
                } //get out we only add metaboxes for set route.
644
                if ($add) {
645
                    $this->_add_metabox($box);
646
                } else {
647
                    $this->_remove_metabox($box);
648
                }
649
            }
650
        }
651
    }
652
653
654
    /**
655
     * Loop through the _remove_metaboxes property and remove metaboxes accordingly.
656
     *
657
     * @access public
658
     * @return void
659
     */
660
    public function remove_metaboxes()
661
    {
662
663
        if (empty($this->_remove_metaboxes)) {
664
            return;
665
        } //get out there are no metaboxes to remove
666
        $this->_handle_metabox_array($this->_remove_metaboxes, false);
667
    }
668
669
670
    /**
671
     * This just handles adding a metabox
672
     *
673
     * @access private
674
     * @param array $args an array of args that have been set for this metabox by the child class
675
     */
676
    private function _add_metabox($args)
677
    {
678
        $current_screen = get_current_screen();
679
        $screen_id = is_object($current_screen) ? $current_screen->id : null;
680
        $func = isset($args['func']) ? $args['func'] : 'some_invalid_callback';
681
        // set defaults
682
        $defaults = array(
683
            'func'          => $func,
684
            'id'            => $this->caller . '_' . $func . '_metabox',
685
            'priority'      => 'default',
686
            'label'         => $this->caller,
687
            'context'       => 'advanced',
688
            'callback_args' => array(),
689
            'page'          => isset($args['page']) ? $args['page'] : $screen_id,
690
        );
691
        $args = wp_parse_args($args, $defaults);
692
        extract($args);
693
        // make sure method exists
694
        if (! method_exists($this, $func)) {
695
            $msg[] = __('There is no corresponding method to display the metabox content', 'event_espresso') . '<br />';
696
            $msg[] = sprintf(
697
                __(
698
                    'The method name given in the array is %s, check the spelling and make sure it exists in the %s class',
699
                    'event_espresso'
700
                ),
701
                $func,
702
                $this->caller
703
            );
704
            throw new EE_Error(implode('||', $msg));
705
        }
706
        // everything checks out so lets add the metabox
707
        add_meta_box($id, $label, array($this, $func), $page, $context, $priority, $callback_args);
708
    }
709
710
711
    private function _remove_metabox($args)
712
    {
713
        $current_screen = get_current_screen();
714
        $screen_id = is_object($current_screen) ? $current_screen->id : null;
715
        $func = isset($args['func']) ? $args['func'] : 'some_invalid_callback';
716
        // set defaults
717
        $defaults = array(
718
            'id'      => isset($args['id'])
719
                ? $args['id']
720
                : $this->_current_route
721
                  . '_'
722
                  . $this->caller
723
                  . '_'
724
                  . $func
725
                  . '_metabox',
726
            'context' => 'default',
727
            'screen'  => isset($args['screen']) ? $args['screen'] : $screen_id,
728
        );
729
        $args = wp_parse_args($args, $defaults);
730
        extract($args);
731
        // everything checks out so lets remove the box!
732
        remove_meta_box($id, $screen, $context);
733
    }
734
}
735