Completed
Branch Gutenberg/event-attendees-bloc... (e27df5)
by
unknown
56:20 queued 41:53
created

EE_Admin   F

Complexity

Total Complexity 80

Size/Duplication

Total Lines 993
Duplicated Lines 0.91 %

Coupling/Cohesion

Components 2
Dependencies 20

Importance

Changes 0
Metric Value
wmc 80
lcom 2
cbo 20
dl 9
loc 993
rs 1.263
c 0
b 0
f 0

35 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 8 2
A hide_admin_pages_except_maintenance_mode() 0 8 1
A reset() 0 5 1
B __construct() 0 24 1
A _define_all_constants() 9 10 2
B filter_plugin_actions() 0 29 4
A get_request() 0 5 1
B init() 0 22 5
A getLoader() 0 7 2
A initModelsReady() 0 21 1
B maybeSetDatetimeWarningNotice() 0 35 4
A remove_pages_from_nav_menu() 0 12 2
C enable_hidden_ee_nav_menu_metaboxes() 0 39 7
A register_custom_nav_menu_boxes() 0 11 1
A modify_edit_post_link() 0 17 3
B ee_cpt_archive_pages() 0 80 4
A _get_extra_nav_menu_pages_items() 0 9 1
B _setup_extra_nav_menu_pages_items() 0 26 3
A route_admin_request() 0 3 1
A wp_loaded() 0 3 1
B admin_init() 0 29 4
A adminInitModelsReady() 0 6 2
A modify_dropdown_pages() 0 20 4
A enqueue_admin_scripts() 0 51 2
A display_admin_notices() 0 4 1
B dashboard_glance_items() 0 39 3
C check_for_invalid_datetime_formats() 0 65 8
A its_eSpresso() 0 4 1
A espresso_admin_footer() 0 4 1
A register_ee_admin_page() 0 18 2
A parse_post_content_on_save() 0 8 1
A reset_page_for_posts_on_change() 0 8 1
A get_persistent_admin_notices() 0 11 1
A dismiss_ee_nag_notice_callback() 0 12 1
A hookIntoWpPluginsPage() 0 7 1

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 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, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use EventEspresso\core\domain\entities\notifications\PersistentAdminNotice;
4
use EventEspresso\core\domain\services\admin\ExitModal;
5
use EventEspresso\core\exceptions\InvalidDataTypeException;
6
use EventEspresso\core\exceptions\InvalidInterfaceException;
7
use EventEspresso\core\interfaces\InterminableInterface;
8
use EventEspresso\core\services\container\exceptions\ServiceNotFoundException;
9
use EventEspresso\core\services\loaders\LoaderFactory;
10
use EventEspresso\core\services\notifications\PersistentAdminNoticeManager;
11
use EventEspresso\core\services\loaders\LoaderInterface;
12
13
/**
14
 * EE_Admin
15
 *
16
 * @package               Event Espresso
17
 * @subpackage            /core/admin/
18
 * @author                Brent Christensen
19
 */
20
final class EE_Admin implements InterminableInterface
21
{
22
23
    /**
24
     * @var EE_Admin $_instance
25
     */
26
    private static $_instance;
27
28
    /**
29
     * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
30
     */
31
    private $persistent_admin_notice_manager;
32
33
    /**
34
     * @var LoaderInterface
35
     */
36
    protected $loader;
37
38
    /**
39
     * @singleton method used to instantiate class object
40
     * @return EE_Admin
41
     * @throws EE_Error
42
     */
43
    public static function instance()
44
    {
45
        // check if class object is instantiated
46
        if (! self::$_instance instanceof EE_Admin) {
47
            self::$_instance = new self();
48
        }
49
        return self::$_instance;
50
    }
51
52
53
    /**
54
     * @return EE_Admin
55
     * @throws EE_Error
56
     */
57
    public static function reset()
58
    {
59
        self::$_instance = null;
60
        return self::instance();
61
    }
62
63
64
    /**
65
     * class constructor
66
     *
67
     * @throws EE_Error
68
     * @throws InvalidDataTypeException
69
     * @throws InvalidInterfaceException
70
     * @throws InvalidArgumentException
71
     */
72
    protected function __construct()
73
    {
74
        // define global EE_Admin constants
75
        $this->_define_all_constants();
76
        // set autoloaders for our admin page classes based on included path information
77
        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
78
        // admin hooks
79
        add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
80
        // load EE_Request_Handler early
81
        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
82
        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
83
        add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
84
        add_action('wp_loaded', array($this, 'wp_loaded'), 100);
85
        add_action('admin_init', array($this, 'admin_init'), 100);
86
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
87
        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
88
        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
89
        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
90
        add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
91
        add_action('load-plugins.php', array($this, 'hookIntoWpPluginsPage'));
92
        // reset Environment config (we only do this on admin page loads);
93
        EE_Registry::instance()->CFG->environment->recheck_values();
94
        do_action('AHEE__EE_Admin__loaded');
95
    }
96
97
98
    /**
99
     * _define_all_constants
100
     * define constants that are set globally for all admin pages
101
     *
102
     * @return void
103
     */
104 View Code Duplication
    private function _define_all_constants()
105
    {
106
        if (! defined('EE_ADMIN_URL')) {
107
            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
108
            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
109
            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
110
            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
111
            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
112
        }
113
    }
114
115
116
    /**
117
     * filter_plugin_actions - adds links to the Plugins page listing
118
     *
119
     * @param    array  $links
120
     * @param    string $plugin
121
     * @return    array
122
     */
123
    public function filter_plugin_actions($links, $plugin)
124
    {
125
        // set $main_file in stone
126
        static $main_file;
127
        // if $main_file is not set yet
128
        if (! $main_file) {
129
            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
130
        }
131
        if ($plugin === $main_file) {
132
            // compare current plugin to this one
133
            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
134
                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
135
                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
136
                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
137
                                    . '</a>';
138
                array_unshift($links, $maintenance_link);
139
            } else {
140
                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
141
                                     . esc_html__('Settings', 'event_espresso')
142
                                     . '</a>';
143
                $events_link = '<a href="admin.php?page=espresso_events">'
144
                               . esc_html__('Events', 'event_espresso')
145
                               . '</a>';
146
                // add before other links
147
                array_unshift($links, $org_settings_link, $events_link);
148
            }
149
        }
150
        return $links;
151
    }
152
153
154
    /**
155
     * _get_request
156
     *
157
     * @return void
158
     * @throws EE_Error
159
     * @throws InvalidArgumentException
160
     * @throws InvalidDataTypeException
161
     * @throws InvalidInterfaceException
162
     * @throws ReflectionException
163
     */
164
    public function get_request()
165
    {
166
        EE_Registry::instance()->load_core('Request_Handler');
167
        EE_Registry::instance()->load_core('CPT_Strategy');
168
    }
169
170
171
    /**
172
     * hide_admin_pages_except_maintenance_mode
173
     *
174
     * @param array $admin_page_folder_names
175
     * @return array
176
     */
177
    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
178
    {
179
        return array(
180
            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
181
            'about'       => EE_ADMIN_PAGES . 'about' . DS,
182
            'support'     => EE_ADMIN_PAGES . 'support' . DS,
183
        );
184
    }
185
186
187
    /**
188
     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
189
     * EE_Front_Controller's init phases have run
190
     *
191
     * @return void
192
     * @throws EE_Error
193
     * @throws InvalidArgumentException
194
     * @throws InvalidDataTypeException
195
     * @throws InvalidInterfaceException
196
     * @throws ReflectionException
197
     * @throws ServiceNotFoundException
198
     */
199
    public function init()
200
    {
201
        // only enable most of the EE_Admin IF we're not in full maintenance mode
202
        if (EE_Maintenance_Mode::instance()->models_can_query()) {
203
            $this->initModelsReady();
204
        }
205
        // run the admin page factory but ONLY if we are doing an ee admin ajax request
206
        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
207
            try {
208
                // this loads the controller for the admin pages which will setup routing etc
209
                EE_Registry::instance()->load_core('Admin_Page_Loader');
210
            } catch (EE_Error $e) {
211
                $e->get_error();
212
            }
213
        }
214
        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
215
        // make sure our CPTs and custom taxonomy metaboxes get shown for first time users
216
        add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
217
        add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
218
        // exclude EE critical pages from all nav menus and wp_list_pages
219
        add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
220
    }
221
222
223
    /**
224
     * Gets the loader (and if it wasn't previously set, sets it)
225
     * @return LoaderInterface
226
     * @throws InvalidArgumentException
227
     * @throws InvalidDataTypeException
228
     * @throws InvalidInterfaceException
229
     */
230
    protected function getLoader()
231
    {
232
        if (! $this->loader instanceof LoaderInterface) {
233
            $this->loader = LoaderFactory::getLoader();
234
        }
235
        return $this->loader;
236
    }
237
238
239
    /**
240
     * Method that's fired on admin requests (including admin ajax) but only when the models are usable
241
     * (ie, the site isn't in maintenance mode)
242
     * @since $VID:$
243
     * @return void
244
     */
245
    protected function initModelsReady()
246
    {
247
        // ok so we want to enable the entire admin
248
        $this->persistent_admin_notice_manager = $this->getLoader()->getShared(
249
            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
250
        );
251
        $this->persistent_admin_notice_manager->setReturnUrl(
252
            EE_Admin_Page::add_query_args_and_nonce(
253
                array(
254
                    'page'   => EE_Registry::instance()->REQ->get('page', ''),
255
                    'action' => EE_Registry::instance()->REQ->get('action', ''),
256
                ),
257
                EE_ADMIN_URL
258
            )
259
        );
260
        $this->maybeSetDatetimeWarningNotice();
261
        // at a glance dashboard widget
262
        add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
263
        // filter for get_edit_post_link used on comments for custom post types
264
        add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
265
    }
266
267
268
    /**
269
     *    get_persistent_admin_notices
270
     *
271
     * @access    public
272
     * @return void
273
     * @throws EE_Error
274
     * @throws InvalidArgumentException
275
     * @throws InvalidDataTypeException
276
     * @throws InvalidInterfaceException
277
     */
278
    public function maybeSetDatetimeWarningNotice()
279
    {
280
        // add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
281
        // @todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
282
        // with this.  But after enough time (indeterminate at this point) we can just remove this notice.
283
        // this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
284
        if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
285
            && ! get_option('timezone_string')
286
            && EEM_Event::instance()->count() > 0
287
        ) {
288
            new PersistentAdminNotice(
289
                'datetime_fix_notice',
290
                sprintf(
291
                    esc_html__(
292
                        '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
293
                        'event_espresso'
294
                    ),
295
                    '<strong>',
296
                    '</strong>',
297
                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
298
                    '</a>',
299
                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
300
                        array(
301
                            'page'   => 'espresso_maintenance_settings',
302
                            'action' => 'datetime_tools',
303
                        ),
304
                        admin_url('admin.php')
305
                    ) . '">'
306
                ),
307
                false,
308
                'manage_options',
309
                'datetime_fix_persistent_notice'
310
            );
311
        }
312
    }
313
314
315
    /**
316
     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
317
     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
318
     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
319
     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
320
     * normal property on the post_type object.  It's found ONLY in this particular context.
321
     *
322
     * @param WP_Post $post_type WP post type object
323
     * @return WP_Post
324
     * @throws InvalidArgumentException
325
     * @throws InvalidDataTypeException
326
     * @throws InvalidInterfaceException
327
     */
328
    public function remove_pages_from_nav_menu($post_type)
329
    {
330
        // if this isn't the "pages" post type let's get out
331
        if ($post_type->name !== 'page') {
332
            return $post_type;
333
        }
334
        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
335
        $post_type->_default_query = array(
336
            'post__not_in' => $critical_pages,
337
        );
338
        return $post_type;
339
    }
340
341
342
    /**
343
     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
344
     * metaboxes get shown as well
345
     *
346
     * @return void
347
     */
348
    public function enable_hidden_ee_nav_menu_metaboxes()
349
    {
350
        global $wp_meta_boxes, $pagenow;
351
        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
352
            return;
353
        }
354
        $user = wp_get_current_user();
355
        // has this been done yet?
356
        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
357
            return;
358
        }
359
360
        $hidden_meta_boxes = get_user_option('metaboxhidden_nav-menus', $user->ID);
361
        $initial_meta_boxes = apply_filters(
362
            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
363
            array(
364
                'nav-menu-theme-locations',
365
                'add-page',
366
                'add-custom-links',
367
                'add-category',
368
                'add-espresso_events',
369
                'add-espresso_venues',
370
                'add-espresso_event_categories',
371
                'add-espresso_venue_categories',
372
                'add-post-type-post',
373
                'add-post-type-page',
374
            )
375
        );
376
377
        if (is_array($hidden_meta_boxes)) {
378
            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
379
                if (in_array($meta_box_id, $initial_meta_boxes, true)) {
380
                    unset($hidden_meta_boxes[ $key ]);
381
                }
382
            }
383
        }
384
        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
385
        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
386
    }
387
388
389
    /**
390
     * This method simply registers custom nav menu boxes for "nav_menus.php route"
391
     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
392
     *
393
     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
394
     *         addons etc.
395
     * @return void
396
     */
397
    public function register_custom_nav_menu_boxes()
398
    {
399
        add_meta_box(
400
            'add-extra-nav-menu-pages',
401
            esc_html__('Event Espresso Pages', 'event_espresso'),
402
            array($this, 'ee_cpt_archive_pages'),
403
            'nav-menus',
404
            'side',
405
            'core'
406
        );
407
    }
408
409
410
    /**
411
     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
412
     *
413
     * @since   4.3.0
414
     * @param string $link the original link generated by wp
415
     * @param int    $id   post id
416
     * @return string  the (maybe) modified link
417
     */
418
    public function modify_edit_post_link($link, $id)
419
    {
420
        if (! $post = get_post($id)) {
421
            return $link;
422
        }
423
        if ($post->post_type === 'espresso_attendees') {
424
            $query_args = array(
425
                'action' => 'edit_attendee',
426
                'post'   => $id,
427
            );
428
            return EEH_URL::add_query_args_and_nonce(
429
                $query_args,
430
                admin_url('admin.php?page=espresso_registrations')
431
            );
432
        }
433
        return $link;
434
    }
435
436
437
    public function ee_cpt_archive_pages()
438
    {
439
        global $nav_menu_selected_id;
440
        $db_fields = false;
441
        $walker = new Walker_Nav_Menu_Checklist($db_fields);
442
        $current_tab = 'event-archives';
443
        $removed_args = array(
444
            'action',
445
            'customlink-tab',
446
            'edit-menu-item',
447
            'menu-item',
448
            'page-tab',
449
            '_wpnonce',
450
        );
451
        ?>
452
        <div id="posttype-extra-nav-menu-pages" class="posttypediv">
453
            <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
454
                <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
455
                    <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
456
                       href="<?php
457
                        if ($nav_menu_selected_id) {
458
                            echo esc_url(
459
                                add_query_arg(
460
                                    'extra-nav-menu-pages-tab',
461
                                    'event-archives',
462
                                    remove_query_arg($removed_args)
463
                                )
464
                            );
465
                        }
466
                        ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
467
                        <?php _e('Event Archive Pages', 'event_espresso'); ?>
468
                    </a>
469
                </li>
470
            </ul><!-- .posttype-tabs -->
471
472
            <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
473
            echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
474
            ?>">
475
                <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
476
                    <?php
477
                    $pages = $this->_get_extra_nav_menu_pages_items();
478
                    $args['walker'] = $walker;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$args was never initialized. Although not strictly required by PHP, it is generally a good practice to add $args = 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...
479
                    echo walk_nav_menu_tree(
480
                        array_map(
481
                            array($this, '_setup_extra_nav_menu_pages_items'),
482
                            $pages
483
                        ),
484
                        0,
485
                        (object) $args
486
                    );
487
                    ?>
488
                </ul>
489
            </div><!-- /.tabs-panel -->
490
491
            <p class="button-controls">
492
                <span class="list-controls">
493
                    <a href="<?php
494
                             echo esc_url(
495
                                 add_query_arg(
496
                                     array(
497
                                         'extra-nav-menu-pages-tab' => 'event-archives',
498
                                         'selectall'                => 1,
499
                                     ),
500
                                     remove_query_arg($removed_args)
501
                                 )
502
                             );
503
                        ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All', 'event_espresso'); ?></a>
504
                </span>
505
                <span class="add-to-menu">
506
                    <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?>
507
                           class="button-secondary submit-add-to-menu right"
508
                           value="<?php esc_attr_e('Add to Menu', 'event_espresso'); ?>" name="add-post-type-menu-item"
509
                           id="<?php echo esc_attr('submit-posttype-extra-nav-menu-pages'); ?>"/>
510
                    <span class="spinner"></span>
511
                </span>
512
            </p>
513
514
        </div><!-- /.posttypediv -->
515
        <?php
516
    }
517
518
519
    /**
520
     * Returns an array of event archive nav items.
521
     *
522
     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
523
     *        method we use for getting the extra nav menu items
524
     * @return array
525
     */
526
    private function _get_extra_nav_menu_pages_items()
527
    {
528
        $menuitems[] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$menuitems was never initialized. Although not strictly required by PHP, it is generally a good practice to add $menuitems = 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...
529
            'title'       => esc_html__('Event List', 'event_espresso'),
530
            'url'         => get_post_type_archive_link('espresso_events'),
531
            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
532
        );
533
        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
534
    }
535
536
537
    /**
538
     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
539
     * the properties and converts it to the menu item object.
540
     *
541
     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
542
     * @param $menu_item_values
543
     * @return stdClass
544
     */
545
    private function _setup_extra_nav_menu_pages_items($menu_item_values)
546
    {
547
        $menu_item = new stdClass();
548
        $keys = array(
549
            'ID'               => 0,
550
            'db_id'            => 0,
551
            'menu_item_parent' => 0,
552
            'object_id'        => -1,
553
            'post_parent'      => 0,
554
            'type'             => 'custom',
555
            'object'           => '',
556
            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
557
            'title'            => '',
558
            'url'              => '',
559
            'target'           => '',
560
            'attr_title'       => '',
561
            'description'      => '',
562
            'classes'          => array(),
563
            'xfn'              => '',
564
        );
565
566
        foreach ($keys as $key => $value) {
567
            $menu_item->{$key} = isset($menu_item_values[ $key ]) ? $menu_item_values[ $key ] : $value;
568
        }
569
        return $menu_item;
570
    }
571
572
573
    /**
574
     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
575
     * EE_Admin_Page route is called.
576
     *
577
     * @return void
578
     */
579
    public function route_admin_request()
580
    {
581
    }
582
583
584
    /**
585
     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
586
     *
587
     * @return void
588
     */
589
    public function wp_loaded()
590
    {
591
    }
592
593
594
    /**
595
     * admin_init
596
     *
597
     * @return void
598
     * @throws EE_Error
599
     * @throws InvalidArgumentException
600
     * @throws InvalidDataTypeException
601
     * @throws InvalidInterfaceException
602
     * @throws ReflectionException
603
     */
604
    public function admin_init()
605
    {
606
        /**
607
         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
608
         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
609
         * - check if doing post processing.
610
         * - check if doing post processing of one of EE CPTs
611
         * - instantiate the corresponding EE CPT model for the post_type being processed.
612
         */
613
        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
614
            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
615
            $custom_post_types = $this->getLoader()->getShared(
616
                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
617
            );
618
            $custom_post_types->getCustomPostTypeModels($_POST['post_type']);
619
        }
620
621
622
        /**
623
         * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
624
         * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
625
         * Pages" tab in the EE General Settings Admin page.
626
         * This is for user-proofing.
627
         */
628
        add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
629
        if (EE_Maintenance_Mode::instance()->models_can_query()) {
630
            $this->adminInitModelsReady();
631
        }
632
    }
633
634
635
    /**
636
     * Runs on admin_init but only if models are usable (ie, we're not in maintenanc emode)
637
     */
638
    protected function adminInitModelsReady()
639
    {
640
        if (function_exists('wp_add_privacy_policy_content')) {
641
            $this->getLoader()->getShared('EventEspresso\core\services\privacy\policy\PrivacyPolicyManager');
642
        }
643
    }
644
645
646
    /**
647
     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
648
     *
649
     * @param string $output Current output.
650
     * @return string
651
     * @throws InvalidArgumentException
652
     * @throws InvalidDataTypeException
653
     * @throws InvalidInterfaceException
654
     */
655
    public function modify_dropdown_pages($output)
656
    {
657
        // get critical pages
658
        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
659
660
        // split current output by line break for easier parsing.
661
        $split_output = explode("\n", $output);
662
663
        // loop through to remove any critical pages from the array.
664
        foreach ($critical_pages as $page_id) {
665
            $needle = 'value="' . $page_id . '"';
666
            foreach ($split_output as $key => $haystack) {
667
                if (strpos($haystack, $needle) !== false) {
668
                    unset($split_output[ $key ]);
669
                }
670
            }
671
        }
672
        // replace output with the new contents
673
        return implode("\n", $split_output);
674
    }
675
676
677
    /**
678
     * enqueue all admin scripts that need loaded for admin pages
679
     *
680
     * @return void
681
     */
682
    public function enqueue_admin_scripts()
683
    {
684
        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
685
        // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
686
        // calls.
687
        wp_enqueue_script(
688
            'ee-inject-wp',
689
            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
690
            array('jquery'),
691
            EVENT_ESPRESSO_VERSION,
692
            true
693
        );
694
        // register cookie script for future dependencies
695
        wp_register_script(
696
            'jquery-cookie',
697
            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
698
            array('jquery'),
699
            '2.1',
700
            true
701
        );
702
        // joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
703
        // via: add_filter('FHEE_load_joyride', '__return_true' );
704
        if (apply_filters('FHEE_load_joyride', false)) {
705
            // joyride style
706
            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
707
            wp_register_style(
708
                'ee-joyride-css',
709
                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
710
                array('joyride-css'),
711
                EVENT_ESPRESSO_VERSION
712
            );
713
            wp_register_script(
714
                'joyride-modernizr',
715
                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
716
                array(),
717
                '2.1',
718
                true
719
            );
720
            // joyride JS
721
            wp_register_script(
722
                'jquery-joyride',
723
                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
724
                array('jquery-cookie', 'joyride-modernizr'),
725
                '2.1',
726
                true
727
            );
728
            // wanna go for a joyride?
729
            wp_enqueue_style('ee-joyride-css');
730
            wp_enqueue_script('jquery-joyride');
731
        }
732
    }
733
734
735
    /**
736
     * display_admin_notices
737
     *
738
     * @return void
739
     */
740
    public function display_admin_notices()
741
    {
742
        echo EE_Error::get_notices();
743
    }
744
745
746
    /**
747
     * @param array $elements
748
     * @return array
749
     * @throws EE_Error
750
     * @throws InvalidArgumentException
751
     * @throws InvalidDataTypeException
752
     * @throws InvalidInterfaceException
753
     */
754
    public function dashboard_glance_items($elements)
755
    {
756
        $elements = is_array($elements) ? $elements : array($elements);
757
        $events = EEM_Event::instance()->count();
758
        $items['events']['url'] = EE_Admin_Page::add_query_args_and_nonce(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$items was never initialized. Although not strictly required by PHP, it is generally a good practice to add $items = 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...
759
            array('page' => 'espresso_events'),
760
            admin_url('admin.php')
761
        );
762
        $items['events']['text'] = sprintf(_n('%s Event', '%s Events', $events, 'event_espresso'), number_format_i18n($events));
763
        $items['events']['title'] = esc_html__('Click to view all Events', 'event_espresso');
764
        $registrations = EEM_Registration::instance()->count(
765
            array(
766
                array(
767
                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
768
                ),
769
            )
770
        );
771
        $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce(
772
            array('page' => 'espresso_registrations'),
773
            admin_url('admin.php')
774
        );
775
        $items['registrations']['text'] = sprintf(
776
            _n('%s Registration', '%s Registrations', $registrations, 'event_espresso'),
777
            number_format_i18n($registrations)
778
        );
779
        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
780
781
        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
782
783
        foreach ($items as $type => $item_properties) {
784
            $elements[] = sprintf(
785
                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
786
                $item_properties['url'],
787
                $item_properties['title'],
788
                $item_properties['text']
789
            );
790
        }
791
        return $elements;
792
    }
793
794
795
    /**
796
     * check_for_invalid_datetime_formats
797
     * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
798
     * their selected format can be parsed by PHP
799
     *
800
     * @param    $value
801
     * @param    $option
802
     * @throws EE_Error
803
     * @return    string
804
     */
805
    public function check_for_invalid_datetime_formats($value, $option)
806
    {
807
        // check for date_format or time_format
808
        switch ($option) {
809
            case 'date_format':
810
                $date_time_format = $value . ' ' . get_option('time_format');
811
                break;
812
            case 'time_format':
813
                $date_time_format = get_option('date_format') . ' ' . $value;
814
                break;
815
            default:
816
                $date_time_format = false;
817
        }
818
        // do we have a date_time format to check ?
819
        if ($date_time_format) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $date_time_format of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
820
            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
821
822
            if (is_array($error_msg)) {
823
                $msg = '<p>'
824
                       . sprintf(
825
                           esc_html__(
826
                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
827
                               'event_espresso'
828
                           ),
829
                           date($date_time_format),
830
                           $date_time_format
831
                       )
832
                       . '</p><p><ul>';
833
834
835
                foreach ($error_msg as $error) {
836
                    $msg .= '<li>' . $error . '</li>';
837
                }
838
839
                $msg .= '</ul></p><p>'
840
                        . sprintf(
841
                            esc_html__(
842
                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
843
                                'event_espresso'
844
                            ),
845
                            '<span style="color:#D54E21;">',
846
                            '</span>'
847
                        )
848
                        . '</p>';
849
850
                // trigger WP settings error
851
                add_settings_error(
852
                    'date_format',
853
                    'date_format',
854
                    $msg
855
                );
856
857
                // set format to something valid
858
                switch ($option) {
859
                    case 'date_format':
860
                        $value = 'F j, Y';
861
                        break;
862
                    case 'time_format':
863
                        $value = 'g:i a';
864
                        break;
865
                }
866
            }
867
        }
868
        return $value;
869
    }
870
871
872
    /**
873
     * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
874
     *
875
     * @param $content
876
     * @return    string
877
     */
878
    public function its_eSpresso($content)
879
    {
880
        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
881
    }
882
883
884
    /**
885
     * espresso_admin_footer
886
     *
887
     * @return    string
888
     */
889
    public function espresso_admin_footer()
890
    {
891
        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
892
    }
893
894
895
    /**
896
     * static method for registering ee admin page.
897
     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
898
     *
899
     * @since      4.3.0
900
     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
901
     * @see        EE_Register_Admin_Page::register()
902
     * @param       $page_basename
903
     * @param       $page_path
904
     * @param array $config
905
     * @return void
906
     * @throws EE_Error
907
     */
908
    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
909
    {
910
        EE_Error::doing_it_wrong(
911
            __METHOD__,
912
            sprintf(
913
                esc_html__(
914
                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
915
                    'event_espresso'
916
                ),
917
                $page_basename
918
            ),
919
            '4.3'
920
        );
921
        if (class_exists('EE_Register_Admin_Page')) {
922
            $config['page_path'] = $page_path;
923
        }
924
        EE_Register_Admin_Page::register($page_basename, $config);
925
    }
926
927
928
    /**
929
     * @deprecated 4.8.41
930
     * @param  int      $post_ID
931
     * @param  \WP_Post $post
932
     * @return void
933
     */
934
    public static function parse_post_content_on_save($post_ID, $post)
935
    {
936
        EE_Error::doing_it_wrong(
937
            __METHOD__,
938
            esc_html__('Usage is deprecated', 'event_espresso'),
939
            '4.8.41'
940
        );
941
    }
942
943
944
    /**
945
     * @deprecated 4.8.41
946
     * @param  $option
947
     * @param  $old_value
948
     * @param  $value
949
     * @return void
950
     */
951
    public function reset_page_for_posts_on_change($option, $old_value, $value)
952
    {
953
        EE_Error::doing_it_wrong(
954
            __METHOD__,
955
            esc_html__('Usage is deprecated', 'event_espresso'),
956
            '4.8.41'
957
        );
958
    }
959
960
961
    /**
962
     * @deprecated 4.9.27
963
     * @return void
964
     */
965
    public function get_persistent_admin_notices()
966
    {
967
        EE_Error::doing_it_wrong(
968
            __METHOD__,
969
            sprintf(
970
                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
971
                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
972
            ),
973
            '4.9.27'
974
        );
975
    }
976
977
978
    /**
979
     * @deprecated 4.9.27
980
     * @throws InvalidInterfaceException
981
     * @throws InvalidDataTypeException
982
     * @throws DomainException
983
     */
984
    public function dismiss_ee_nag_notice_callback()
985
    {
986
        EE_Error::doing_it_wrong(
987
            __METHOD__,
988
            sprintf(
989
                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
990
                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
991
            ),
992
            '4.9.27'
993
        );
994
        $this->persistent_admin_notice_manager->dismissNotice();
995
    }
996
997
998
    /**
999
     * Callback on load-plugins.php hook for setting up anything hooking into the wp plugins page.
1000
     *
1001
     * @throws InvalidArgumentException
1002
     * @throws InvalidDataTypeException
1003
     * @throws InvalidInterfaceException
1004
     */
1005
    public function hookIntoWpPluginsPage()
1006
    {
1007
        $this->getLoader()->getShared('EventEspresso\core\domain\services\admin\ExitModal');
1008
        $this->getLoader()
1009
                     ->getShared('EventEspresso\core\domain\services\admin\PluginUpsells')
1010
                     ->decafUpsells();
1011
    }
1012
}
1013