Completed
Branch EDTR/master (2c3e96)
by
unknown
19:06 queued 09:20
created
core/admin/EE_Admin.core.php 2 patches
Indentation   +990 added lines, -990 removed lines patch added patch discarded remove patch
@@ -20,490 +20,490 @@  discard block
 block discarded – undo
20 20
 final class EE_Admin implements InterminableInterface
21 21
 {
22 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 $loader
35
-     */
36
-    protected $loader;
37
-
38
-    /**
39
-     * @var RequestInterface $request
40
-     */
41
-    protected $request;
42
-
43
-
44
-    /**
45
-     * @singleton method used to instantiate class object
46
-     * @param LoaderInterface  $loader
47
-     * @param RequestInterface $request
48
-     * @return EE_Admin
49
-     * @throws EE_Error
50
-     */
51
-    public static function instance(LoaderInterface $loader = null, RequestInterface $request = null)
52
-    {
53
-        // check if class object is instantiated
54
-        if (! EE_Admin::$_instance instanceof EE_Admin) {
55
-            EE_Admin::$_instance = new EE_Admin($loader, $request);
56
-        }
57
-        return EE_Admin::$_instance;
58
-    }
59
-
60
-
61
-    /**
62
-     * @return EE_Admin
63
-     * @throws EE_Error
64
-     */
65
-    public static function reset()
66
-    {
67
-        EE_Admin::$_instance = null;
68
-        $loader = LoaderFactory::getLoader();
69
-        $request = $loader->getShared('EventEspresso\core\services\request\Request');
70
-        return EE_Admin::instance($loader, $request);
71
-    }
72
-
73
-
74
-    /**
75
-     * class constructor
76
-     *
77
-     * @param LoaderInterface  $loader
78
-     * @param RequestInterface $request
79
-     * @throws EE_Error
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidInterfaceException
82
-     * @throws InvalidArgumentException
83
-     */
84
-    protected function __construct(LoaderInterface $loader, RequestInterface $request)
85
-    {
86
-        $this->loader = $loader;
87
-        $this->request = $request;
88
-        // define global EE_Admin constants
89
-        $this->_define_all_constants();
90
-        // set autoloaders for our admin page classes based on included path information
91
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_ADMIN);
92
-        // reset Environment config (we only do this on admin page loads);
93
-        EE_Registry::instance()->CFG->environment->recheck_values();
94
-        // load EE_Request_Handler early
95
-        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
96
-        add_action('admin_init', array($this, 'admin_init'), 100);
97
-        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
98
-        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
99
-        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
100
-        if (! $this->request->isAjax()) {
101
-            // admin hooks
102
-            add_filter('plugin_action_links', [$this, 'filter_plugin_actions'], 10, 2);
103
-            add_filter('admin_footer_text', [$this, 'espresso_admin_footer']);
104
-            add_action('load-plugins.php', [$this, 'hookIntoWpPluginsPage']);
105
-            add_action('display_post_states', [$this, 'displayStateForCriticalPages'], 10, 2);
106
-            add_filter('plugin_row_meta', [$this, 'addLinksToPluginRowMeta'], 10, 2);
107
-        }
108
-        do_action('AHEE__EE_Admin__loaded');
109
-    }
110
-
111
-
112
-    /**
113
-     * _define_all_constants
114
-     * define constants that are set globally for all admin pages
115
-     *
116
-     * @return void
117
-     */
118
-    private function _define_all_constants()
119
-    {
120
-        if (! defined('EE_ADMIN_URL')) {
121
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
122
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
123
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates/');
124
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
125
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
126
-        }
127
-    }
128
-
129
-
130
-    /**
131
-     * filter_plugin_actions - adds links to the Plugins page listing
132
-     *
133
-     * @param    array  $links
134
-     * @param    string $plugin
135
-     * @return    array
136
-     */
137
-    public function filter_plugin_actions($links, $plugin)
138
-    {
139
-        // set $main_file in stone
140
-        static $main_file;
141
-        // if $main_file is not set yet
142
-        if (! $main_file) {
143
-            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
144
-        }
145
-        if ($plugin === $main_file) {
146
-            // compare current plugin to this one
147
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
148
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
149
-                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
150
-                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
151
-                                    . '</a>';
152
-                array_unshift($links, $maintenance_link);
153
-            } else {
154
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
155
-                                     . esc_html__('Settings', 'event_espresso')
156
-                                     . '</a>';
157
-                $events_link = '<a href="admin.php?page=espresso_events">'
158
-                               . esc_html__('Events', 'event_espresso')
159
-                               . '</a>';
160
-                // add before other links
161
-                array_unshift($links, $org_settings_link, $events_link);
162
-            }
163
-        }
164
-        return $links;
165
-    }
166
-
167
-
168
-    /**
169
-     * hide_admin_pages_except_maintenance_mode
170
-     *
171
-     * @param array $admin_page_folder_names
172
-     * @return array
173
-     */
174
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
175
-    {
176
-        return array(
177
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance/',
178
-            'about'       => EE_ADMIN_PAGES . 'about/',
179
-            'support'     => EE_ADMIN_PAGES . 'support/',
180
-        );
181
-    }
182
-
183
-
184
-    /**
185
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
186
-     * EE_Front_Controller's init phases have run
187
-     *
188
-     * @return void
189
-     * @throws EE_Error
190
-     * @throws InvalidArgumentException
191
-     * @throws InvalidDataTypeException
192
-     * @throws InvalidInterfaceException
193
-     * @throws ReflectionException
194
-     * @throws ServiceNotFoundException
195
-     */
196
-    public function init()
197
-    {
198
-        // only enable most of the EE_Admin IF we're not in full maintenance mode
199
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
200
-            $this->initModelsReady();
201
-        }
202
-        // run the admin page factory but ONLY if we are doing an ee admin ajax request
203
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
204
-            try {
205
-                // this loads the controller for the admin pages which will setup routing etc
206
-                $admin_page_loader = $this->loader->getShared('EE_Admin_Page_Loader');
207
-                $admin_page_loader->init();
208
-            } catch (EE_Error $e) {
209
-                $e->get_error();
210
-            }
211
-        }
212
-        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
213
-        if (! $this->request->isAjax()) {
214
-            // make sure our CPTs and custom taxonomy metaboxes get shown for first time users
215
-            add_action('admin_head', [$this, 'enable_hidden_ee_nav_menu_metaboxes'], 10);
216
-            add_action('admin_head', [$this, 'register_custom_nav_menu_boxes'], 10);
217
-            // exclude EE critical pages from all nav menus and wp_list_pages
218
-            add_filter('nav_menu_meta_box_object', [$this, 'remove_pages_from_nav_menu'], 10);
219
-        }
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
-     *
243
-     * @return void
244
-     * @throws EE_Error
245
-     * @throws EE_Error
246
-     * @since 4.9.63.p
247
-     */
248
-    protected function initModelsReady()
249
-    {
250
-        // ok so we want to enable the entire admin
251
-        $this->persistent_admin_notice_manager = $this->loader->getShared(
252
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
253
-        );
254
-        $this->persistent_admin_notice_manager->setReturnUrl(
255
-            EE_Admin_Page::add_query_args_and_nonce(
256
-                array(
257
-                    'page'   => $this->request->getRequestParam('page', ''),
258
-                    'action' => $this->request->getRequestParam('action', ''),
259
-                ),
260
-                EE_ADMIN_URL
261
-            )
262
-        );
263
-        $this->maybeSetDatetimeWarningNotice();
264
-        // at a glance dashboard widget
265
-        add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
266
-        // filter for get_edit_post_link used on comments for custom post types
267
-        add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
268
-    }
269
-
270
-
271
-    /**
272
-     *    get_persistent_admin_notices
273
-     *
274
-     * @access    public
275
-     * @return void
276
-     * @throws EE_Error
277
-     * @throws InvalidArgumentException
278
-     * @throws InvalidDataTypeException
279
-     * @throws InvalidInterfaceException
280
-     */
281
-    public function maybeSetDatetimeWarningNotice()
282
-    {
283
-        // add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
284
-        // @todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
285
-        // with this.  But after enough time (indeterminate at this point) we can just remove this notice.
286
-        // this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
287
-        if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
288
-            && ! get_option('timezone_string')
289
-            && EEM_Event::instance()->count() > 0
290
-        ) {
291
-            new PersistentAdminNotice(
292
-                'datetime_fix_notice',
293
-                sprintf(
294
-                    esc_html__(
295
-                        '%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.',
296
-                        'event_espresso'
297
-                    ),
298
-                    '<strong>',
299
-                    '</strong>',
300
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
301
-                    '</a>',
302
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
303
-                        array(
304
-                            'page'   => 'espresso_maintenance_settings',
305
-                            'action' => 'datetime_tools',
306
-                        ),
307
-                        admin_url('admin.php')
308
-                    ) . '">'
309
-                ),
310
-                false,
311
-                'manage_options',
312
-                'datetime_fix_persistent_notice'
313
-            );
314
-        }
315
-    }
316
-
317
-
318
-    /**
319
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
320
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
321
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
322
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
323
-     * normal property on the post_type object.  It's found ONLY in this particular context.
324
-     *
325
-     * @param WP_Post $post_type WP post type object
326
-     * @return WP_Post
327
-     * @throws InvalidArgumentException
328
-     * @throws InvalidDataTypeException
329
-     * @throws InvalidInterfaceException
330
-     */
331
-    public function remove_pages_from_nav_menu($post_type)
332
-    {
333
-        // if this isn't the "pages" post type let's get out
334
-        if ($post_type->name !== 'page') {
335
-            return $post_type;
336
-        }
337
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
338
-        $post_type->_default_query = array(
339
-            'post__not_in' => $critical_pages,
340
-        );
341
-        return $post_type;
342
-    }
343
-
344
-
345
-    /**
346
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
347
-     * metaboxes get shown as well
348
-     *
349
-     * @return void
350
-     */
351
-    public function enable_hidden_ee_nav_menu_metaboxes()
352
-    {
353
-        global $wp_meta_boxes, $pagenow;
354
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
355
-            return;
356
-        }
357
-        $user = wp_get_current_user();
358
-        // has this been done yet?
359
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
360
-            return;
361
-        }
362
-
363
-        $hidden_meta_boxes = get_user_option('metaboxhidden_nav-menus', $user->ID);
364
-        $initial_meta_boxes = apply_filters(
365
-            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
366
-            array(
367
-                'nav-menu-theme-locations',
368
-                'add-page',
369
-                'add-custom-links',
370
-                'add-category',
371
-                'add-espresso_events',
372
-                'add-espresso_venues',
373
-                'add-espresso_event_categories',
374
-                'add-espresso_venue_categories',
375
-                'add-post-type-post',
376
-                'add-post-type-page',
377
-            )
378
-        );
379
-
380
-        if (is_array($hidden_meta_boxes)) {
381
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
382
-                if (in_array($meta_box_id, $initial_meta_boxes, true)) {
383
-                    unset($hidden_meta_boxes[ $key ]);
384
-                }
385
-            }
386
-        }
387
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
388
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
389
-    }
390
-
391
-
392
-    /**
393
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
394
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
395
-     *
396
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
397
-     *         addons etc.
398
-     * @return void
399
-     */
400
-    public function register_custom_nav_menu_boxes()
401
-    {
402
-        add_meta_box(
403
-            'add-extra-nav-menu-pages',
404
-            esc_html__('Event Espresso Pages', 'event_espresso'),
405
-            array($this, 'ee_cpt_archive_pages'),
406
-            'nav-menus',
407
-            'side',
408
-            'core'
409
-        );
410
-    }
411
-
412
-
413
-    /**
414
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
415
-     *
416
-     * @since   4.3.0
417
-     * @param string $link the original link generated by wp
418
-     * @param int    $id   post id
419
-     * @return string  the (maybe) modified link
420
-     */
421
-    public function modify_edit_post_link($link, $id)
422
-    {
423
-        if (! $post = get_post($id)) {
424
-            return $link;
425
-        }
426
-        if ($post->post_type === 'espresso_attendees') {
427
-            $query_args = array(
428
-                'action' => 'edit_attendee',
429
-                'post'   => $id,
430
-            );
431
-            return EEH_URL::add_query_args_and_nonce(
432
-                $query_args,
433
-                admin_url('admin.php?page=espresso_registrations')
434
-            );
435
-        }
436
-        return $link;
437
-    }
438
-
439
-
440
-    public function ee_cpt_archive_pages()
441
-    {
442
-        global $nav_menu_selected_id;
443
-        $db_fields = false;
444
-        $walker = new Walker_Nav_Menu_Checklist($db_fields);
445
-        $current_tab = 'event-archives';
446
-        $removed_args = array(
447
-            'action',
448
-            'customlink-tab',
449
-            'edit-menu-item',
450
-            'menu-item',
451
-            'page-tab',
452
-            '_wpnonce',
453
-        );
454
-        ?>
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 $loader
35
+	 */
36
+	protected $loader;
37
+
38
+	/**
39
+	 * @var RequestInterface $request
40
+	 */
41
+	protected $request;
42
+
43
+
44
+	/**
45
+	 * @singleton method used to instantiate class object
46
+	 * @param LoaderInterface  $loader
47
+	 * @param RequestInterface $request
48
+	 * @return EE_Admin
49
+	 * @throws EE_Error
50
+	 */
51
+	public static function instance(LoaderInterface $loader = null, RequestInterface $request = null)
52
+	{
53
+		// check if class object is instantiated
54
+		if (! EE_Admin::$_instance instanceof EE_Admin) {
55
+			EE_Admin::$_instance = new EE_Admin($loader, $request);
56
+		}
57
+		return EE_Admin::$_instance;
58
+	}
59
+
60
+
61
+	/**
62
+	 * @return EE_Admin
63
+	 * @throws EE_Error
64
+	 */
65
+	public static function reset()
66
+	{
67
+		EE_Admin::$_instance = null;
68
+		$loader = LoaderFactory::getLoader();
69
+		$request = $loader->getShared('EventEspresso\core\services\request\Request');
70
+		return EE_Admin::instance($loader, $request);
71
+	}
72
+
73
+
74
+	/**
75
+	 * class constructor
76
+	 *
77
+	 * @param LoaderInterface  $loader
78
+	 * @param RequestInterface $request
79
+	 * @throws EE_Error
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidInterfaceException
82
+	 * @throws InvalidArgumentException
83
+	 */
84
+	protected function __construct(LoaderInterface $loader, RequestInterface $request)
85
+	{
86
+		$this->loader = $loader;
87
+		$this->request = $request;
88
+		// define global EE_Admin constants
89
+		$this->_define_all_constants();
90
+		// set autoloaders for our admin page classes based on included path information
91
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_ADMIN);
92
+		// reset Environment config (we only do this on admin page loads);
93
+		EE_Registry::instance()->CFG->environment->recheck_values();
94
+		// load EE_Request_Handler early
95
+		add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
96
+		add_action('admin_init', array($this, 'admin_init'), 100);
97
+		add_action('admin_notices', array($this, 'display_admin_notices'), 10);
98
+		add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
99
+		add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
100
+		if (! $this->request->isAjax()) {
101
+			// admin hooks
102
+			add_filter('plugin_action_links', [$this, 'filter_plugin_actions'], 10, 2);
103
+			add_filter('admin_footer_text', [$this, 'espresso_admin_footer']);
104
+			add_action('load-plugins.php', [$this, 'hookIntoWpPluginsPage']);
105
+			add_action('display_post_states', [$this, 'displayStateForCriticalPages'], 10, 2);
106
+			add_filter('plugin_row_meta', [$this, 'addLinksToPluginRowMeta'], 10, 2);
107
+		}
108
+		do_action('AHEE__EE_Admin__loaded');
109
+	}
110
+
111
+
112
+	/**
113
+	 * _define_all_constants
114
+	 * define constants that are set globally for all admin pages
115
+	 *
116
+	 * @return void
117
+	 */
118
+	private function _define_all_constants()
119
+	{
120
+		if (! defined('EE_ADMIN_URL')) {
121
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
122
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
123
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates/');
124
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
125
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
126
+		}
127
+	}
128
+
129
+
130
+	/**
131
+	 * filter_plugin_actions - adds links to the Plugins page listing
132
+	 *
133
+	 * @param    array  $links
134
+	 * @param    string $plugin
135
+	 * @return    array
136
+	 */
137
+	public function filter_plugin_actions($links, $plugin)
138
+	{
139
+		// set $main_file in stone
140
+		static $main_file;
141
+		// if $main_file is not set yet
142
+		if (! $main_file) {
143
+			$main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
144
+		}
145
+		if ($plugin === $main_file) {
146
+			// compare current plugin to this one
147
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
148
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
149
+									. ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
150
+									. esc_html__('Maintenance Mode Active', 'event_espresso')
151
+									. '</a>';
152
+				array_unshift($links, $maintenance_link);
153
+			} else {
154
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
155
+									 . esc_html__('Settings', 'event_espresso')
156
+									 . '</a>';
157
+				$events_link = '<a href="admin.php?page=espresso_events">'
158
+							   . esc_html__('Events', 'event_espresso')
159
+							   . '</a>';
160
+				// add before other links
161
+				array_unshift($links, $org_settings_link, $events_link);
162
+			}
163
+		}
164
+		return $links;
165
+	}
166
+
167
+
168
+	/**
169
+	 * hide_admin_pages_except_maintenance_mode
170
+	 *
171
+	 * @param array $admin_page_folder_names
172
+	 * @return array
173
+	 */
174
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
175
+	{
176
+		return array(
177
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance/',
178
+			'about'       => EE_ADMIN_PAGES . 'about/',
179
+			'support'     => EE_ADMIN_PAGES . 'support/',
180
+		);
181
+	}
182
+
183
+
184
+	/**
185
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
186
+	 * EE_Front_Controller's init phases have run
187
+	 *
188
+	 * @return void
189
+	 * @throws EE_Error
190
+	 * @throws InvalidArgumentException
191
+	 * @throws InvalidDataTypeException
192
+	 * @throws InvalidInterfaceException
193
+	 * @throws ReflectionException
194
+	 * @throws ServiceNotFoundException
195
+	 */
196
+	public function init()
197
+	{
198
+		// only enable most of the EE_Admin IF we're not in full maintenance mode
199
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
200
+			$this->initModelsReady();
201
+		}
202
+		// run the admin page factory but ONLY if we are doing an ee admin ajax request
203
+		if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
204
+			try {
205
+				// this loads the controller for the admin pages which will setup routing etc
206
+				$admin_page_loader = $this->loader->getShared('EE_Admin_Page_Loader');
207
+				$admin_page_loader->init();
208
+			} catch (EE_Error $e) {
209
+				$e->get_error();
210
+			}
211
+		}
212
+		add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
213
+		if (! $this->request->isAjax()) {
214
+			// make sure our CPTs and custom taxonomy metaboxes get shown for first time users
215
+			add_action('admin_head', [$this, 'enable_hidden_ee_nav_menu_metaboxes'], 10);
216
+			add_action('admin_head', [$this, 'register_custom_nav_menu_boxes'], 10);
217
+			// exclude EE critical pages from all nav menus and wp_list_pages
218
+			add_filter('nav_menu_meta_box_object', [$this, 'remove_pages_from_nav_menu'], 10);
219
+		}
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
+	 *
243
+	 * @return void
244
+	 * @throws EE_Error
245
+	 * @throws EE_Error
246
+	 * @since 4.9.63.p
247
+	 */
248
+	protected function initModelsReady()
249
+	{
250
+		// ok so we want to enable the entire admin
251
+		$this->persistent_admin_notice_manager = $this->loader->getShared(
252
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
253
+		);
254
+		$this->persistent_admin_notice_manager->setReturnUrl(
255
+			EE_Admin_Page::add_query_args_and_nonce(
256
+				array(
257
+					'page'   => $this->request->getRequestParam('page', ''),
258
+					'action' => $this->request->getRequestParam('action', ''),
259
+				),
260
+				EE_ADMIN_URL
261
+			)
262
+		);
263
+		$this->maybeSetDatetimeWarningNotice();
264
+		// at a glance dashboard widget
265
+		add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
266
+		// filter for get_edit_post_link used on comments for custom post types
267
+		add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
268
+	}
269
+
270
+
271
+	/**
272
+	 *    get_persistent_admin_notices
273
+	 *
274
+	 * @access    public
275
+	 * @return void
276
+	 * @throws EE_Error
277
+	 * @throws InvalidArgumentException
278
+	 * @throws InvalidDataTypeException
279
+	 * @throws InvalidInterfaceException
280
+	 */
281
+	public function maybeSetDatetimeWarningNotice()
282
+	{
283
+		// add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
284
+		// @todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
285
+		// with this.  But after enough time (indeterminate at this point) we can just remove this notice.
286
+		// this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
287
+		if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
288
+			&& ! get_option('timezone_string')
289
+			&& EEM_Event::instance()->count() > 0
290
+		) {
291
+			new PersistentAdminNotice(
292
+				'datetime_fix_notice',
293
+				sprintf(
294
+					esc_html__(
295
+						'%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.',
296
+						'event_espresso'
297
+					),
298
+					'<strong>',
299
+					'</strong>',
300
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
301
+					'</a>',
302
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
303
+						array(
304
+							'page'   => 'espresso_maintenance_settings',
305
+							'action' => 'datetime_tools',
306
+						),
307
+						admin_url('admin.php')
308
+					) . '">'
309
+				),
310
+				false,
311
+				'manage_options',
312
+				'datetime_fix_persistent_notice'
313
+			);
314
+		}
315
+	}
316
+
317
+
318
+	/**
319
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
320
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
321
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
322
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
323
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
324
+	 *
325
+	 * @param WP_Post $post_type WP post type object
326
+	 * @return WP_Post
327
+	 * @throws InvalidArgumentException
328
+	 * @throws InvalidDataTypeException
329
+	 * @throws InvalidInterfaceException
330
+	 */
331
+	public function remove_pages_from_nav_menu($post_type)
332
+	{
333
+		// if this isn't the "pages" post type let's get out
334
+		if ($post_type->name !== 'page') {
335
+			return $post_type;
336
+		}
337
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
338
+		$post_type->_default_query = array(
339
+			'post__not_in' => $critical_pages,
340
+		);
341
+		return $post_type;
342
+	}
343
+
344
+
345
+	/**
346
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
347
+	 * metaboxes get shown as well
348
+	 *
349
+	 * @return void
350
+	 */
351
+	public function enable_hidden_ee_nav_menu_metaboxes()
352
+	{
353
+		global $wp_meta_boxes, $pagenow;
354
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
355
+			return;
356
+		}
357
+		$user = wp_get_current_user();
358
+		// has this been done yet?
359
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
360
+			return;
361
+		}
362
+
363
+		$hidden_meta_boxes = get_user_option('metaboxhidden_nav-menus', $user->ID);
364
+		$initial_meta_boxes = apply_filters(
365
+			'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
366
+			array(
367
+				'nav-menu-theme-locations',
368
+				'add-page',
369
+				'add-custom-links',
370
+				'add-category',
371
+				'add-espresso_events',
372
+				'add-espresso_venues',
373
+				'add-espresso_event_categories',
374
+				'add-espresso_venue_categories',
375
+				'add-post-type-post',
376
+				'add-post-type-page',
377
+			)
378
+		);
379
+
380
+		if (is_array($hidden_meta_boxes)) {
381
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
382
+				if (in_array($meta_box_id, $initial_meta_boxes, true)) {
383
+					unset($hidden_meta_boxes[ $key ]);
384
+				}
385
+			}
386
+		}
387
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
388
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
389
+	}
390
+
391
+
392
+	/**
393
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
394
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
395
+	 *
396
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
397
+	 *         addons etc.
398
+	 * @return void
399
+	 */
400
+	public function register_custom_nav_menu_boxes()
401
+	{
402
+		add_meta_box(
403
+			'add-extra-nav-menu-pages',
404
+			esc_html__('Event Espresso Pages', 'event_espresso'),
405
+			array($this, 'ee_cpt_archive_pages'),
406
+			'nav-menus',
407
+			'side',
408
+			'core'
409
+		);
410
+	}
411
+
412
+
413
+	/**
414
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
415
+	 *
416
+	 * @since   4.3.0
417
+	 * @param string $link the original link generated by wp
418
+	 * @param int    $id   post id
419
+	 * @return string  the (maybe) modified link
420
+	 */
421
+	public function modify_edit_post_link($link, $id)
422
+	{
423
+		if (! $post = get_post($id)) {
424
+			return $link;
425
+		}
426
+		if ($post->post_type === 'espresso_attendees') {
427
+			$query_args = array(
428
+				'action' => 'edit_attendee',
429
+				'post'   => $id,
430
+			);
431
+			return EEH_URL::add_query_args_and_nonce(
432
+				$query_args,
433
+				admin_url('admin.php?page=espresso_registrations')
434
+			);
435
+		}
436
+		return $link;
437
+	}
438
+
439
+
440
+	public function ee_cpt_archive_pages()
441
+	{
442
+		global $nav_menu_selected_id;
443
+		$db_fields = false;
444
+		$walker = new Walker_Nav_Menu_Checklist($db_fields);
445
+		$current_tab = 'event-archives';
446
+		$removed_args = array(
447
+			'action',
448
+			'customlink-tab',
449
+			'edit-menu-item',
450
+			'menu-item',
451
+			'page-tab',
452
+			'_wpnonce',
453
+		);
454
+		?>
455 455
         <div id="posttype-extra-nav-menu-pages" class="posttypediv">
456 456
             <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
457 457
                 <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
458 458
                     <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
459 459
                        href="<?php
460
-                        if ($nav_menu_selected_id) {
461
-                            echo esc_url(
462
-                                add_query_arg(
463
-                                    'extra-nav-menu-pages-tab',
464
-                                    'event-archives',
465
-                                    remove_query_arg($removed_args)
466
-                                )
467
-                            );
468
-                        }
469
-                        ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
460
+						if ($nav_menu_selected_id) {
461
+							echo esc_url(
462
+								add_query_arg(
463
+									'extra-nav-menu-pages-tab',
464
+									'event-archives',
465
+									remove_query_arg($removed_args)
466
+								)
467
+							);
468
+						}
469
+						?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
470 470
                         <?php esc_html_e('Event Archive Pages', 'event_espresso'); ?>
471 471
                     </a>
472 472
                 </li>
473 473
             </ul><!-- .posttype-tabs -->
474 474
 
475 475
             <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
476
-            echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
477
-            ?>">
476
+			echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
477
+			?>">
478 478
                 <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
479 479
                     <?php
480
-                    $pages = $this->_get_extra_nav_menu_pages_items();
481
-                    $args['walker'] = $walker;
482
-                    echo walk_nav_menu_tree(
483
-                        array_map(
484
-                            array($this, '_setup_extra_nav_menu_pages_items'),
485
-                            $pages
486
-                        ),
487
-                        0,
488
-                        (object) $args
489
-                    );
490
-                    ?>
480
+					$pages = $this->_get_extra_nav_menu_pages_items();
481
+					$args['walker'] = $walker;
482
+					echo walk_nav_menu_tree(
483
+						array_map(
484
+							array($this, '_setup_extra_nav_menu_pages_items'),
485
+							$pages
486
+						),
487
+						0,
488
+						(object) $args
489
+					);
490
+					?>
491 491
                 </ul>
492 492
             </div><!-- /.tabs-panel -->
493 493
 
494 494
             <p class="button-controls">
495 495
                 <span class="list-controls">
496 496
                     <a href="<?php
497
-                             echo esc_url(
498
-                                 add_query_arg(
499
-                                     array(
500
-                                         'extra-nav-menu-pages-tab' => 'event-archives',
501
-                                         'selectall'                => 1,
502
-                                     ),
503
-                                     remove_query_arg($removed_args)
504
-                                 )
505
-                             );
506
-                        ?>#posttype-extra-nav-menu-pages" class="select-all"><?php esc_html_e('Select All', 'event_espresso'); ?></a>
497
+							 echo esc_url(
498
+								 add_query_arg(
499
+									 array(
500
+										 'extra-nav-menu-pages-tab' => 'event-archives',
501
+										 'selectall'                => 1,
502
+									 ),
503
+									 remove_query_arg($removed_args)
504
+								 )
505
+							 );
506
+						?>#posttype-extra-nav-menu-pages" class="select-all"><?php esc_html_e('Select All', 'event_espresso'); ?></a>
507 507
                 </span>
508 508
                 <span class="add-to-menu">
509 509
                     <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?>
@@ -516,529 +516,529 @@  discard block
 block discarded – undo
516 516
 
517 517
         </div><!-- /.posttypediv -->
518 518
         <?php
519
-    }
520
-
521
-
522
-    /**
523
-     * Returns an array of event archive nav items.
524
-     *
525
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
526
-     *        method we use for getting the extra nav menu items
527
-     * @return array
528
-     */
529
-    private function _get_extra_nav_menu_pages_items()
530
-    {
531
-        $menuitems[] = array(
532
-            'title'       => esc_html__('Event List', 'event_espresso'),
533
-            'url'         => get_post_type_archive_link('espresso_events'),
534
-            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
535
-        );
536
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
537
-    }
538
-
539
-
540
-    /**
541
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
542
-     * the properties and converts it to the menu item object.
543
-     *
544
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
545
-     * @param $menu_item_values
546
-     * @return stdClass
547
-     */
548
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
549
-    {
550
-        $menu_item = new stdClass();
551
-        $keys = array(
552
-            'ID'               => 0,
553
-            'db_id'            => 0,
554
-            'menu_item_parent' => 0,
555
-            'object_id'        => -1,
556
-            'post_parent'      => 0,
557
-            'type'             => 'custom',
558
-            'object'           => '',
559
-            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
560
-            'title'            => '',
561
-            'url'              => '',
562
-            'target'           => '',
563
-            'attr_title'       => '',
564
-            'description'      => '',
565
-            'classes'          => array(),
566
-            'xfn'              => '',
567
-        );
568
-
569
-        foreach ($keys as $key => $value) {
570
-            $menu_item->{$key} = isset($menu_item_values[ $key ]) ? $menu_item_values[ $key ] : $value;
571
-        }
572
-        return $menu_item;
573
-    }
574
-
575
-
576
-    /**
577
-     * admin_init
578
-     *
579
-     * @return void
580
-     * @throws InvalidArgumentException
581
-     * @throws InvalidDataTypeException
582
-     * @throws InvalidInterfaceException
583
-     */
584
-    public function admin_init()
585
-    {
586
-        /**
587
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
588
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
589
-         * - check if doing post processing.
590
-         * - check if doing post processing of one of EE CPTs
591
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
592
-         */
593
-        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
594
-            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
595
-            $custom_post_types = $this->loader->getShared(
596
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
597
-            );
598
-            $custom_post_types->getCustomPostTypeModels($_POST['post_type']);
599
-        }
600
-
601
-        if (! $this->request->isAjax()) {
602
-            /**
603
-             * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
604
-             * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
605
-             * Pages" tab in the EE General Settings Admin page.
606
-             * This is for user-proofing.
607
-             */
608
-            add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
609
-            if (EE_Maintenance_Mode::instance()->models_can_query()) {
610
-                $this->adminInitModelsReady();
611
-            }
612
-        }
613
-    }
614
-
615
-
616
-    /**
617
-     * Runs on admin_init but only if models are usable (ie, we're not in maintenance mode)
618
-     */
619
-    protected function adminInitModelsReady()
620
-    {
621
-        if (function_exists('wp_add_privacy_policy_content')) {
622
-            $this->loader->getShared('EventEspresso\core\services\privacy\policy\PrivacyPolicyManager');
623
-        }
624
-    }
625
-
626
-
627
-    /**
628
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
629
-     *
630
-     * @param string $output Current output.
631
-     * @return string
632
-     * @throws InvalidArgumentException
633
-     * @throws InvalidDataTypeException
634
-     * @throws InvalidInterfaceException
635
-     */
636
-    public function modify_dropdown_pages($output)
637
-    {
638
-        // get critical pages
639
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
640
-
641
-        // split current output by line break for easier parsing.
642
-        $split_output = explode("\n", $output);
643
-
644
-        // loop through to remove any critical pages from the array.
645
-        foreach ($critical_pages as $page_id) {
646
-            $needle = 'value="' . $page_id . '"';
647
-            foreach ($split_output as $key => $haystack) {
648
-                if (strpos($haystack, $needle) !== false) {
649
-                    unset($split_output[ $key ]);
650
-                }
651
-            }
652
-        }
653
-        // replace output with the new contents
654
-        return implode("\n", $split_output);
655
-    }
656
-
657
-
658
-    /**
659
-     * display_admin_notices
660
-     *
661
-     * @return void
662
-     */
663
-    public function display_admin_notices()
664
-    {
665
-        echo EE_Error::get_notices();
666
-    }
667
-
668
-
669
-    /**
670
-     * @param array $elements
671
-     * @return array
672
-     * @throws EE_Error
673
-     * @throws InvalidArgumentException
674
-     * @throws InvalidDataTypeException
675
-     * @throws InvalidInterfaceException
676
-     */
677
-    public function dashboard_glance_items($elements)
678
-    {
679
-        $elements = is_array($elements) ? $elements : array($elements);
680
-        $events = EEM_Event::instance()->count();
681
-        $items['events']['url'] = EE_Admin_Page::add_query_args_and_nonce(
682
-            array('page' => 'espresso_events'),
683
-            admin_url('admin.php')
684
-        );
685
-        $items['events']['text'] = sprintf(
686
-            esc_html(
687
-                _n('%s Event', '%s Events', $events, 'event_espresso')
688
-            ),
689
-            number_format_i18n($events)
690
-        );
691
-        $items['events']['title'] = esc_html__('Click to view all Events', 'event_espresso');
692
-        $registrations = EEM_Registration::instance()->count(
693
-            array(
694
-                array(
695
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
696
-                ),
697
-            )
698
-        );
699
-        $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce(
700
-            array('page' => 'espresso_registrations'),
701
-            admin_url('admin.php')
702
-        );
703
-        $items['registrations']['text'] = sprintf(
704
-            esc_html(
705
-                _n('%s Registration', '%s Registrations', $registrations, 'event_espresso')
706
-            ),
707
-            number_format_i18n($registrations)
708
-        );
709
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
710
-
711
-        $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
712
-
713
-        foreach ($items as $type => $item_properties) {
714
-            $elements[] = sprintf(
715
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
716
-                $item_properties['url'],
717
-                $item_properties['title'],
718
-                $item_properties['text']
719
-            );
720
-        }
721
-        return $elements;
722
-    }
723
-
724
-
725
-    /**
726
-     * check_for_invalid_datetime_formats
727
-     * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
728
-     * their selected format can be parsed by PHP
729
-     *
730
-     * @param    $value
731
-     * @param    $option
732
-     * @return    string
733
-     */
734
-    public function check_for_invalid_datetime_formats($value, $option)
735
-    {
736
-        // check for date_format or time_format
737
-        switch ($option) {
738
-            case 'date_format':
739
-                $date_time_format = $value . ' ' . get_option('time_format');
740
-                break;
741
-            case 'time_format':
742
-                $date_time_format = get_option('date_format') . ' ' . $value;
743
-                break;
744
-            default:
745
-                $date_time_format = false;
746
-        }
747
-        // do we have a date_time format to check ?
748
-        if ($date_time_format) {
749
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
750
-
751
-            if (is_array($error_msg)) {
752
-                $msg = '<p>'
753
-                       . sprintf(
754
-                           esc_html__(
755
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
756
-                               'event_espresso'
757
-                           ),
758
-                           date($date_time_format),
759
-                           $date_time_format
760
-                       )
761
-                       . '</p><p><ul>';
762
-
763
-
764
-                foreach ($error_msg as $error) {
765
-                    $msg .= '<li>' . $error . '</li>';
766
-                }
767
-
768
-                $msg .= '</ul></p><p>'
769
-                        . sprintf(
770
-                            esc_html__(
771
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
772
-                                'event_espresso'
773
-                            ),
774
-                            '<span style="color:#D54E21;">',
775
-                            '</span>'
776
-                        )
777
-                        . '</p>';
778
-
779
-                // trigger WP settings error
780
-                add_settings_error(
781
-                    'date_format',
782
-                    'date_format',
783
-                    $msg
784
-                );
785
-
786
-                // set format to something valid
787
-                switch ($option) {
788
-                    case 'date_format':
789
-                        $value = 'F j, Y';
790
-                        break;
791
-                    case 'time_format':
792
-                        $value = 'g:i a';
793
-                        break;
794
-                }
795
-            }
796
-        }
797
-        return $value;
798
-    }
799
-
800
-
801
-    /**
802
-     * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
803
-     *
804
-     * @param $content
805
-     * @return    string
806
-     */
807
-    public function its_eSpresso($content)
808
-    {
809
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
810
-    }
811
-
812
-
813
-    /**
814
-     * espresso_admin_footer
815
-     *
816
-     * @return    string
817
-     */
818
-    public function espresso_admin_footer()
819
-    {
820
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
821
-    }
822
-
823
-
824
-    /**
825
-     * Hooks into the "post states" filter in a wp post type list table.
826
-     *
827
-     * @param array   $post_states
828
-     * @param WP_Post $post
829
-     * @return array
830
-     * @throws InvalidArgumentException
831
-     * @throws InvalidDataTypeException
832
-     * @throws InvalidInterfaceException
833
-     */
834
-    public function displayStateForCriticalPages($post_states, $post)
835
-    {
836
-        $post_states = (array) $post_states;
837
-        if (! $post instanceof WP_Post || $post->post_type !== 'page') {
838
-            return $post_states;
839
-        }
840
-        /** @var EE_Core_Config $config */
841
-        $config = $this->loader->getShared('EE_Config')->core;
842
-        if (in_array($post->ID, $config->get_critical_pages_array(), true)) {
843
-            $post_states[] = sprintf(
844
-                /* Translators: Using company name - Event Espresso Critical Page */
845
-                esc_html__('%s Critical Page', 'event_espresso'),
846
-                'Event Espresso'
847
-            );
848
-        }
849
-        return $post_states;
850
-    }
851
-
852
-
853
-    /**
854
-     * Show documentation links on the plugins page
855
-     *
856
-     * @param mixed $meta Plugin Row Meta
857
-     * @param mixed $file Plugin Base file
858
-     * @return array
859
-     */
860
-    public function addLinksToPluginRowMeta($meta, $file)
861
-    {
862
-        if (EE_PLUGIN_BASENAME === $file) {
863
-            $row_meta = array(
864
-                'docs' => '<a href="https://eventespresso.com/support/documentation/versioned-docs/?doc_ver=ee4"'
865
-                          . ' aria-label="'
866
-                          . esc_attr__('View Event Espresso documentation', 'event_espresso')
867
-                          . '">'
868
-                          . esc_html__('Docs', 'event_espresso')
869
-                          . '</a>',
870
-                'api'  => '<a href="https://github.com/eventespresso/event-espresso-core/tree/master/docs/C--REST-API"'
871
-                          . ' aria-label="'
872
-                          . esc_attr__('View Event Espresso API docs', 'event_espresso')
873
-                          . '">'
874
-                          . esc_html__('API docs', 'event_espresso')
875
-                          . '</a>',
876
-            );
877
-            return array_merge($meta, $row_meta);
878
-        }
879
-        return (array) $meta;
880
-    }
881
-
882
-     /**************************************************************************************/
883
-     /************************************* DEPRECATED *************************************/
884
-     /**************************************************************************************/
885
-
886
-
887
-    /**
888
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
889
-     * EE_Admin_Page route is called.
890
-     *
891
-     * @return void
892
-     */
893
-    public function route_admin_request()
894
-    {
895
-    }
896
-
897
-
898
-    /**
899
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
900
-     *
901
-     * @return void
902
-     */
903
-    public function wp_loaded()
904
-    {
905
-    }
906
-
907
-
908
-    /**
909
-     * static method for registering ee admin page.
910
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
911
-     *
912
-     * @param       $page_basename
913
-     * @param       $page_path
914
-     * @param array $config
915
-     * @return void
916
-     * @throws EE_Error
917
-     * @see        EE_Register_Admin_Page::register()
918
-     * @since      4.3.0
919
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
920
-     */
921
-    public static function register_ee_admin_page($page_basename, $page_path, $config = [])
922
-    {
923
-        EE_Error::doing_it_wrong(
924
-            __METHOD__,
925
-            sprintf(
926
-                esc_html__(
927
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
928
-                    'event_espresso'
929
-                ),
930
-                $page_basename
931
-            ),
932
-            '4.3'
933
-        );
934
-        if (class_exists('EE_Register_Admin_Page')) {
935
-            $config['page_path'] = $page_path;
936
-        }
937
-        EE_Register_Admin_Page::register($page_basename, $config);
938
-    }
939
-
940
-
941
-    /**
942
-     * @param int      $post_ID
943
-     * @param \WP_Post $post
944
-     * @return void
945
-     * @deprecated 4.8.41
946
-     */
947
-    public static function parse_post_content_on_save($post_ID, $post)
948
-    {
949
-        EE_Error::doing_it_wrong(
950
-            __METHOD__,
951
-            esc_html__('Usage is deprecated', 'event_espresso'),
952
-            '4.8.41'
953
-        );
954
-    }
955
-
956
-
957
-    /**
958
-     * @param  $option
959
-     * @param  $old_value
960
-     * @param  $value
961
-     * @return void
962
-     * @deprecated 4.8.41
963
-     */
964
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
965
-    {
966
-        EE_Error::doing_it_wrong(
967
-            __METHOD__,
968
-            esc_html__('Usage is deprecated', 'event_espresso'),
969
-            '4.8.41'
970
-        );
971
-    }
972
-
973
-
974
-    /**
975
-     * @return void
976
-     * @deprecated 4.9.27
977
-     */
978
-    public function get_persistent_admin_notices()
979
-    {
980
-        EE_Error::doing_it_wrong(
981
-            __METHOD__,
982
-            sprintf(
983
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
984
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
985
-            ),
986
-            '4.9.27'
987
-        );
988
-    }
989
-
990
-
991
-    /**
992
-     * @throws InvalidInterfaceException
993
-     * @throws InvalidDataTypeException
994
-     * @throws DomainException
995
-     * @deprecated 4.9.27
996
-     */
997
-    public function dismiss_ee_nag_notice_callback()
998
-    {
999
-        EE_Error::doing_it_wrong(
1000
-            __METHOD__,
1001
-            sprintf(
1002
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1003
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1004
-            ),
1005
-            '4.9.27'
1006
-        );
1007
-        $this->persistent_admin_notice_manager->dismissNotice();
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * @return void
1013
-     * @deprecated $VID:$
1014
-     */
1015
-    public function enqueue_admin_scripts()
1016
-    {
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * @return RequestInterface
1023
-     * @deprecated $VID:$
1024
-     */
1025
-    public function get_request()
1026
-    {
1027
-        EE_Error::doing_it_wrong(
1028
-            __METHOD__,
1029
-            sprintf(
1030
-                esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1031
-                'EventEspresso\core\services\request\Request'
1032
-            ),
1033
-            '$VID:$'
1034
-        );
1035
-        return $this->request;
1036
-    }
1037
-
1038
-    /**
1039
-     * @deprecated $VID:$
1040
-     */
1041
-    public function hookIntoWpPluginsPage()
1042
-    {
1043
-    }
519
+	}
520
+
521
+
522
+	/**
523
+	 * Returns an array of event archive nav items.
524
+	 *
525
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
526
+	 *        method we use for getting the extra nav menu items
527
+	 * @return array
528
+	 */
529
+	private function _get_extra_nav_menu_pages_items()
530
+	{
531
+		$menuitems[] = array(
532
+			'title'       => esc_html__('Event List', 'event_espresso'),
533
+			'url'         => get_post_type_archive_link('espresso_events'),
534
+			'description' => esc_html__('Archive page for all events.', 'event_espresso'),
535
+		);
536
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
537
+	}
538
+
539
+
540
+	/**
541
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
542
+	 * the properties and converts it to the menu item object.
543
+	 *
544
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
545
+	 * @param $menu_item_values
546
+	 * @return stdClass
547
+	 */
548
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
549
+	{
550
+		$menu_item = new stdClass();
551
+		$keys = array(
552
+			'ID'               => 0,
553
+			'db_id'            => 0,
554
+			'menu_item_parent' => 0,
555
+			'object_id'        => -1,
556
+			'post_parent'      => 0,
557
+			'type'             => 'custom',
558
+			'object'           => '',
559
+			'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
560
+			'title'            => '',
561
+			'url'              => '',
562
+			'target'           => '',
563
+			'attr_title'       => '',
564
+			'description'      => '',
565
+			'classes'          => array(),
566
+			'xfn'              => '',
567
+		);
568
+
569
+		foreach ($keys as $key => $value) {
570
+			$menu_item->{$key} = isset($menu_item_values[ $key ]) ? $menu_item_values[ $key ] : $value;
571
+		}
572
+		return $menu_item;
573
+	}
574
+
575
+
576
+	/**
577
+	 * admin_init
578
+	 *
579
+	 * @return void
580
+	 * @throws InvalidArgumentException
581
+	 * @throws InvalidDataTypeException
582
+	 * @throws InvalidInterfaceException
583
+	 */
584
+	public function admin_init()
585
+	{
586
+		/**
587
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
588
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
589
+		 * - check if doing post processing.
590
+		 * - check if doing post processing of one of EE CPTs
591
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
592
+		 */
593
+		if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
594
+			/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
595
+			$custom_post_types = $this->loader->getShared(
596
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
597
+			);
598
+			$custom_post_types->getCustomPostTypeModels($_POST['post_type']);
599
+		}
600
+
601
+		if (! $this->request->isAjax()) {
602
+			/**
603
+			 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
604
+			 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
605
+			 * Pages" tab in the EE General Settings Admin page.
606
+			 * This is for user-proofing.
607
+			 */
608
+			add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
609
+			if (EE_Maintenance_Mode::instance()->models_can_query()) {
610
+				$this->adminInitModelsReady();
611
+			}
612
+		}
613
+	}
614
+
615
+
616
+	/**
617
+	 * Runs on admin_init but only if models are usable (ie, we're not in maintenance mode)
618
+	 */
619
+	protected function adminInitModelsReady()
620
+	{
621
+		if (function_exists('wp_add_privacy_policy_content')) {
622
+			$this->loader->getShared('EventEspresso\core\services\privacy\policy\PrivacyPolicyManager');
623
+		}
624
+	}
625
+
626
+
627
+	/**
628
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
629
+	 *
630
+	 * @param string $output Current output.
631
+	 * @return string
632
+	 * @throws InvalidArgumentException
633
+	 * @throws InvalidDataTypeException
634
+	 * @throws InvalidInterfaceException
635
+	 */
636
+	public function modify_dropdown_pages($output)
637
+	{
638
+		// get critical pages
639
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
640
+
641
+		// split current output by line break for easier parsing.
642
+		$split_output = explode("\n", $output);
643
+
644
+		// loop through to remove any critical pages from the array.
645
+		foreach ($critical_pages as $page_id) {
646
+			$needle = 'value="' . $page_id . '"';
647
+			foreach ($split_output as $key => $haystack) {
648
+				if (strpos($haystack, $needle) !== false) {
649
+					unset($split_output[ $key ]);
650
+				}
651
+			}
652
+		}
653
+		// replace output with the new contents
654
+		return implode("\n", $split_output);
655
+	}
656
+
657
+
658
+	/**
659
+	 * display_admin_notices
660
+	 *
661
+	 * @return void
662
+	 */
663
+	public function display_admin_notices()
664
+	{
665
+		echo EE_Error::get_notices();
666
+	}
667
+
668
+
669
+	/**
670
+	 * @param array $elements
671
+	 * @return array
672
+	 * @throws EE_Error
673
+	 * @throws InvalidArgumentException
674
+	 * @throws InvalidDataTypeException
675
+	 * @throws InvalidInterfaceException
676
+	 */
677
+	public function dashboard_glance_items($elements)
678
+	{
679
+		$elements = is_array($elements) ? $elements : array($elements);
680
+		$events = EEM_Event::instance()->count();
681
+		$items['events']['url'] = EE_Admin_Page::add_query_args_and_nonce(
682
+			array('page' => 'espresso_events'),
683
+			admin_url('admin.php')
684
+		);
685
+		$items['events']['text'] = sprintf(
686
+			esc_html(
687
+				_n('%s Event', '%s Events', $events, 'event_espresso')
688
+			),
689
+			number_format_i18n($events)
690
+		);
691
+		$items['events']['title'] = esc_html__('Click to view all Events', 'event_espresso');
692
+		$registrations = EEM_Registration::instance()->count(
693
+			array(
694
+				array(
695
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
696
+				),
697
+			)
698
+		);
699
+		$items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce(
700
+			array('page' => 'espresso_registrations'),
701
+			admin_url('admin.php')
702
+		);
703
+		$items['registrations']['text'] = sprintf(
704
+			esc_html(
705
+				_n('%s Registration', '%s Registrations', $registrations, 'event_espresso')
706
+			),
707
+			number_format_i18n($registrations)
708
+		);
709
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
710
+
711
+		$items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
712
+
713
+		foreach ($items as $type => $item_properties) {
714
+			$elements[] = sprintf(
715
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
716
+				$item_properties['url'],
717
+				$item_properties['title'],
718
+				$item_properties['text']
719
+			);
720
+		}
721
+		return $elements;
722
+	}
723
+
724
+
725
+	/**
726
+	 * check_for_invalid_datetime_formats
727
+	 * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
728
+	 * their selected format can be parsed by PHP
729
+	 *
730
+	 * @param    $value
731
+	 * @param    $option
732
+	 * @return    string
733
+	 */
734
+	public function check_for_invalid_datetime_formats($value, $option)
735
+	{
736
+		// check for date_format or time_format
737
+		switch ($option) {
738
+			case 'date_format':
739
+				$date_time_format = $value . ' ' . get_option('time_format');
740
+				break;
741
+			case 'time_format':
742
+				$date_time_format = get_option('date_format') . ' ' . $value;
743
+				break;
744
+			default:
745
+				$date_time_format = false;
746
+		}
747
+		// do we have a date_time format to check ?
748
+		if ($date_time_format) {
749
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
750
+
751
+			if (is_array($error_msg)) {
752
+				$msg = '<p>'
753
+					   . sprintf(
754
+						   esc_html__(
755
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
756
+							   'event_espresso'
757
+						   ),
758
+						   date($date_time_format),
759
+						   $date_time_format
760
+					   )
761
+					   . '</p><p><ul>';
762
+
763
+
764
+				foreach ($error_msg as $error) {
765
+					$msg .= '<li>' . $error . '</li>';
766
+				}
767
+
768
+				$msg .= '</ul></p><p>'
769
+						. sprintf(
770
+							esc_html__(
771
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
772
+								'event_espresso'
773
+							),
774
+							'<span style="color:#D54E21;">',
775
+							'</span>'
776
+						)
777
+						. '</p>';
778
+
779
+				// trigger WP settings error
780
+				add_settings_error(
781
+					'date_format',
782
+					'date_format',
783
+					$msg
784
+				);
785
+
786
+				// set format to something valid
787
+				switch ($option) {
788
+					case 'date_format':
789
+						$value = 'F j, Y';
790
+						break;
791
+					case 'time_format':
792
+						$value = 'g:i a';
793
+						break;
794
+				}
795
+			}
796
+		}
797
+		return $value;
798
+	}
799
+
800
+
801
+	/**
802
+	 * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
803
+	 *
804
+	 * @param $content
805
+	 * @return    string
806
+	 */
807
+	public function its_eSpresso($content)
808
+	{
809
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
810
+	}
811
+
812
+
813
+	/**
814
+	 * espresso_admin_footer
815
+	 *
816
+	 * @return    string
817
+	 */
818
+	public function espresso_admin_footer()
819
+	{
820
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
821
+	}
822
+
823
+
824
+	/**
825
+	 * Hooks into the "post states" filter in a wp post type list table.
826
+	 *
827
+	 * @param array   $post_states
828
+	 * @param WP_Post $post
829
+	 * @return array
830
+	 * @throws InvalidArgumentException
831
+	 * @throws InvalidDataTypeException
832
+	 * @throws InvalidInterfaceException
833
+	 */
834
+	public function displayStateForCriticalPages($post_states, $post)
835
+	{
836
+		$post_states = (array) $post_states;
837
+		if (! $post instanceof WP_Post || $post->post_type !== 'page') {
838
+			return $post_states;
839
+		}
840
+		/** @var EE_Core_Config $config */
841
+		$config = $this->loader->getShared('EE_Config')->core;
842
+		if (in_array($post->ID, $config->get_critical_pages_array(), true)) {
843
+			$post_states[] = sprintf(
844
+				/* Translators: Using company name - Event Espresso Critical Page */
845
+				esc_html__('%s Critical Page', 'event_espresso'),
846
+				'Event Espresso'
847
+			);
848
+		}
849
+		return $post_states;
850
+	}
851
+
852
+
853
+	/**
854
+	 * Show documentation links on the plugins page
855
+	 *
856
+	 * @param mixed $meta Plugin Row Meta
857
+	 * @param mixed $file Plugin Base file
858
+	 * @return array
859
+	 */
860
+	public function addLinksToPluginRowMeta($meta, $file)
861
+	{
862
+		if (EE_PLUGIN_BASENAME === $file) {
863
+			$row_meta = array(
864
+				'docs' => '<a href="https://eventespresso.com/support/documentation/versioned-docs/?doc_ver=ee4"'
865
+						  . ' aria-label="'
866
+						  . esc_attr__('View Event Espresso documentation', 'event_espresso')
867
+						  . '">'
868
+						  . esc_html__('Docs', 'event_espresso')
869
+						  . '</a>',
870
+				'api'  => '<a href="https://github.com/eventespresso/event-espresso-core/tree/master/docs/C--REST-API"'
871
+						  . ' aria-label="'
872
+						  . esc_attr__('View Event Espresso API docs', 'event_espresso')
873
+						  . '">'
874
+						  . esc_html__('API docs', 'event_espresso')
875
+						  . '</a>',
876
+			);
877
+			return array_merge($meta, $row_meta);
878
+		}
879
+		return (array) $meta;
880
+	}
881
+
882
+	 /**************************************************************************************/
883
+	 /************************************* DEPRECATED *************************************/
884
+	 /**************************************************************************************/
885
+
886
+
887
+	/**
888
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
889
+	 * EE_Admin_Page route is called.
890
+	 *
891
+	 * @return void
892
+	 */
893
+	public function route_admin_request()
894
+	{
895
+	}
896
+
897
+
898
+	/**
899
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
900
+	 *
901
+	 * @return void
902
+	 */
903
+	public function wp_loaded()
904
+	{
905
+	}
906
+
907
+
908
+	/**
909
+	 * static method for registering ee admin page.
910
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
911
+	 *
912
+	 * @param       $page_basename
913
+	 * @param       $page_path
914
+	 * @param array $config
915
+	 * @return void
916
+	 * @throws EE_Error
917
+	 * @see        EE_Register_Admin_Page::register()
918
+	 * @since      4.3.0
919
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
920
+	 */
921
+	public static function register_ee_admin_page($page_basename, $page_path, $config = [])
922
+	{
923
+		EE_Error::doing_it_wrong(
924
+			__METHOD__,
925
+			sprintf(
926
+				esc_html__(
927
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
928
+					'event_espresso'
929
+				),
930
+				$page_basename
931
+			),
932
+			'4.3'
933
+		);
934
+		if (class_exists('EE_Register_Admin_Page')) {
935
+			$config['page_path'] = $page_path;
936
+		}
937
+		EE_Register_Admin_Page::register($page_basename, $config);
938
+	}
939
+
940
+
941
+	/**
942
+	 * @param int      $post_ID
943
+	 * @param \WP_Post $post
944
+	 * @return void
945
+	 * @deprecated 4.8.41
946
+	 */
947
+	public static function parse_post_content_on_save($post_ID, $post)
948
+	{
949
+		EE_Error::doing_it_wrong(
950
+			__METHOD__,
951
+			esc_html__('Usage is deprecated', 'event_espresso'),
952
+			'4.8.41'
953
+		);
954
+	}
955
+
956
+
957
+	/**
958
+	 * @param  $option
959
+	 * @param  $old_value
960
+	 * @param  $value
961
+	 * @return void
962
+	 * @deprecated 4.8.41
963
+	 */
964
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
965
+	{
966
+		EE_Error::doing_it_wrong(
967
+			__METHOD__,
968
+			esc_html__('Usage is deprecated', 'event_espresso'),
969
+			'4.8.41'
970
+		);
971
+	}
972
+
973
+
974
+	/**
975
+	 * @return void
976
+	 * @deprecated 4.9.27
977
+	 */
978
+	public function get_persistent_admin_notices()
979
+	{
980
+		EE_Error::doing_it_wrong(
981
+			__METHOD__,
982
+			sprintf(
983
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
984
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
985
+			),
986
+			'4.9.27'
987
+		);
988
+	}
989
+
990
+
991
+	/**
992
+	 * @throws InvalidInterfaceException
993
+	 * @throws InvalidDataTypeException
994
+	 * @throws DomainException
995
+	 * @deprecated 4.9.27
996
+	 */
997
+	public function dismiss_ee_nag_notice_callback()
998
+	{
999
+		EE_Error::doing_it_wrong(
1000
+			__METHOD__,
1001
+			sprintf(
1002
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1003
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
1004
+			),
1005
+			'4.9.27'
1006
+		);
1007
+		$this->persistent_admin_notice_manager->dismissNotice();
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * @return void
1013
+	 * @deprecated $VID:$
1014
+	 */
1015
+	public function enqueue_admin_scripts()
1016
+	{
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * @return RequestInterface
1023
+	 * @deprecated $VID:$
1024
+	 */
1025
+	public function get_request()
1026
+	{
1027
+		EE_Error::doing_it_wrong(
1028
+			__METHOD__,
1029
+			sprintf(
1030
+				esc_html__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
1031
+				'EventEspresso\core\services\request\Request'
1032
+			),
1033
+			'$VID:$'
1034
+		);
1035
+		return $this->request;
1036
+	}
1037
+
1038
+	/**
1039
+	 * @deprecated $VID:$
1040
+	 */
1041
+	public function hookIntoWpPluginsPage()
1042
+	{
1043
+	}
1044 1044
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
     public static function instance(LoaderInterface $loader = null, RequestInterface $request = null)
52 52
     {
53 53
         // check if class object is instantiated
54
-        if (! EE_Admin::$_instance instanceof EE_Admin) {
54
+        if ( ! EE_Admin::$_instance instanceof EE_Admin) {
55 55
             EE_Admin::$_instance = new EE_Admin($loader, $request);
56 56
         }
57 57
         return EE_Admin::$_instance;
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
         add_action('admin_notices', array($this, 'display_admin_notices'), 10);
98 98
         add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
99 99
         add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
100
-        if (! $this->request->isAjax()) {
100
+        if ( ! $this->request->isAjax()) {
101 101
             // admin hooks
102 102
             add_filter('plugin_action_links', [$this, 'filter_plugin_actions'], 10, 2);
103 103
             add_filter('admin_footer_text', [$this, 'espresso_admin_footer']);
@@ -117,11 +117,11 @@  discard block
 block discarded – undo
117 117
      */
118 118
     private function _define_all_constants()
119 119
     {
120
-        if (! defined('EE_ADMIN_URL')) {
121
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
122
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
123
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates/');
124
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
120
+        if ( ! defined('EE_ADMIN_URL')) {
121
+            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL.'core/admin/');
122
+            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL.'admin_pages/');
123
+            define('EE_ADMIN_TEMPLATE', EE_ADMIN.'templates/');
124
+            define('WP_ADMIN_PATH', ABSPATH.'wp-admin/');
125 125
             define('WP_AJAX_URL', admin_url('admin-ajax.php'));
126 126
         }
127 127
     }
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
         // set $main_file in stone
140 140
         static $main_file;
141 141
         // if $main_file is not set yet
142
-        if (! $main_file) {
142
+        if ( ! $main_file) {
143 143
             $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
144 144
         }
145 145
         if ($plugin === $main_file) {
@@ -174,9 +174,9 @@  discard block
 block discarded – undo
174 174
     public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
175 175
     {
176 176
         return array(
177
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance/',
178
-            'about'       => EE_ADMIN_PAGES . 'about/',
179
-            'support'     => EE_ADMIN_PAGES . 'support/',
177
+            'maintenance' => EE_ADMIN_PAGES.'maintenance/',
178
+            'about'       => EE_ADMIN_PAGES.'about/',
179
+            'support'     => EE_ADMIN_PAGES.'support/',
180 180
         );
181 181
     }
182 182
 
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
             $this->initModelsReady();
201 201
         }
202 202
         // run the admin page factory but ONLY if we are doing an ee admin ajax request
203
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
203
+        if ( ! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
204 204
             try {
205 205
                 // this loads the controller for the admin pages which will setup routing etc
206 206
                 $admin_page_loader = $this->loader->getShared('EE_Admin_Page_Loader');
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
             }
211 211
         }
212 212
         add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
213
-        if (! $this->request->isAjax()) {
213
+        if ( ! $this->request->isAjax()) {
214 214
             // make sure our CPTs and custom taxonomy metaboxes get shown for first time users
215 215
             add_action('admin_head', [$this, 'enable_hidden_ee_nav_menu_metaboxes'], 10);
216 216
             add_action('admin_head', [$this, 'register_custom_nav_menu_boxes'], 10);
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
      */
230 230
     protected function getLoader()
231 231
     {
232
-        if (! $this->loader instanceof LoaderInterface) {
232
+        if ( ! $this->loader instanceof LoaderInterface) {
233 233
             $this->loader = LoaderFactory::getLoader();
234 234
         }
235 235
         return $this->loader;
@@ -299,13 +299,13 @@  discard block
 block discarded – undo
299 299
                     '</strong>',
300 300
                     '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
301 301
                     '</a>',
302
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
302
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
303 303
                         array(
304 304
                             'page'   => 'espresso_maintenance_settings',
305 305
                             'action' => 'datetime_tools',
306 306
                         ),
307 307
                         admin_url('admin.php')
308
-                    ) . '">'
308
+                    ).'">'
309 309
                 ),
310 310
                 false,
311 311
                 'manage_options',
@@ -351,7 +351,7 @@  discard block
 block discarded – undo
351 351
     public function enable_hidden_ee_nav_menu_metaboxes()
352 352
     {
353 353
         global $wp_meta_boxes, $pagenow;
354
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
354
+        if ( ! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
355 355
             return;
356 356
         }
357 357
         $user = wp_get_current_user();
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
         if (is_array($hidden_meta_boxes)) {
381 381
             foreach ($hidden_meta_boxes as $key => $meta_box_id) {
382 382
                 if (in_array($meta_box_id, $initial_meta_boxes, true)) {
383
-                    unset($hidden_meta_boxes[ $key ]);
383
+                    unset($hidden_meta_boxes[$key]);
384 384
                 }
385 385
             }
386 386
         }
@@ -420,7 +420,7 @@  discard block
 block discarded – undo
420 420
      */
421 421
     public function modify_edit_post_link($link, $id)
422 422
     {
423
-        if (! $post = get_post($id)) {
423
+        if ( ! $post = get_post($id)) {
424 424
             return $link;
425 425
         }
426 426
         if ($post->post_type === 'espresso_attendees') {
@@ -567,7 +567,7 @@  discard block
 block discarded – undo
567 567
         );
568 568
 
569 569
         foreach ($keys as $key => $value) {
570
-            $menu_item->{$key} = isset($menu_item_values[ $key ]) ? $menu_item_values[ $key ] : $value;
570
+            $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
571 571
         }
572 572
         return $menu_item;
573 573
     }
@@ -598,7 +598,7 @@  discard block
 block discarded – undo
598 598
             $custom_post_types->getCustomPostTypeModels($_POST['post_type']);
599 599
         }
600 600
 
601
-        if (! $this->request->isAjax()) {
601
+        if ( ! $this->request->isAjax()) {
602 602
             /**
603 603
              * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
604 604
              * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
@@ -643,10 +643,10 @@  discard block
 block discarded – undo
643 643
 
644 644
         // loop through to remove any critical pages from the array.
645 645
         foreach ($critical_pages as $page_id) {
646
-            $needle = 'value="' . $page_id . '"';
646
+            $needle = 'value="'.$page_id.'"';
647 647
             foreach ($split_output as $key => $haystack) {
648 648
                 if (strpos($haystack, $needle) !== false) {
649
-                    unset($split_output[ $key ]);
649
+                    unset($split_output[$key]);
650 650
                 }
651 651
             }
652 652
         }
@@ -712,7 +712,7 @@  discard block
 block discarded – undo
712 712
 
713 713
         foreach ($items as $type => $item_properties) {
714 714
             $elements[] = sprintf(
715
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
715
+                '<a class="ee-dashboard-link-'.$type.'" href="%s" title="%s">%s</a>',
716 716
                 $item_properties['url'],
717 717
                 $item_properties['title'],
718 718
                 $item_properties['text']
@@ -736,10 +736,10 @@  discard block
 block discarded – undo
736 736
         // check for date_format or time_format
737 737
         switch ($option) {
738 738
             case 'date_format':
739
-                $date_time_format = $value . ' ' . get_option('time_format');
739
+                $date_time_format = $value.' '.get_option('time_format');
740 740
                 break;
741 741
             case 'time_format':
742
-                $date_time_format = get_option('date_format') . ' ' . $value;
742
+                $date_time_format = get_option('date_format').' '.$value;
743 743
                 break;
744 744
             default:
745 745
                 $date_time_format = false;
@@ -762,7 +762,7 @@  discard block
 block discarded – undo
762 762
 
763 763
 
764 764
                 foreach ($error_msg as $error) {
765
-                    $msg .= '<li>' . $error . '</li>';
765
+                    $msg .= '<li>'.$error.'</li>';
766 766
                 }
767 767
 
768 768
                 $msg .= '</ul></p><p>'
@@ -834,7 +834,7 @@  discard block
 block discarded – undo
834 834
     public function displayStateForCriticalPages($post_states, $post)
835 835
     {
836 836
         $post_states = (array) $post_states;
837
-        if (! $post instanceof WP_Post || $post->post_type !== 'page') {
837
+        if ( ! $post instanceof WP_Post || $post->post_type !== 'page') {
838 838
             return $post_states;
839 839
         }
840 840
         /** @var EE_Core_Config $config */
Please login to merge, or discard this patch.
core/services/routing/Route.php 1 patch
Indentation   +216 added lines, -216 removed lines patch added patch discarded remove patch
@@ -25,220 +25,220 @@
 block discarded – undo
25 25
 abstract class Route implements RouteInterface
26 26
 {
27 27
 
28
-    /**
29
-     * @var AssetManagerInterface $asset_manager
30
-     */
31
-    protected $asset_manager;
32
-
33
-    /**
34
-     * @var EE_Dependency_Map $dependency_map
35
-     */
36
-    protected $dependency_map;
37
-
38
-    /**
39
-     * @var JsonDataNode $data_node
40
-     */
41
-    protected $data_node;
42
-
43
-    /**
44
-     * @var LoaderInterface $loader
45
-     */
46
-    protected $loader;
47
-
48
-    /**
49
-     * @var RequestInterface $request
50
-     */
51
-    protected $request;
52
-
53
-    /**
54
-     * @var RouteMatchSpecificationInterface $specification
55
-     */
56
-    protected $specification;
57
-
58
-    /**
59
-     * @var boolean $handled
60
-     */
61
-    private $handled = false;
62
-
63
-    /**
64
-     * @var array $default_dependencies
65
-     */
66
-    protected static $default_dependencies = [
67
-        'EE_Dependency_Map'                           => EE_Dependency_Map::load_from_cache,
68
-        'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
69
-        'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
70
-    ];
71
-
72
-    /**
73
-     * @var array $full_dependencies
74
-     */
75
-    protected static $full_dependencies = [
76
-        'EE_Dependency_Map'                                                                          => EE_Dependency_Map::load_from_cache,
77
-        'EventEspresso\core\services\loaders\Loader'                                                 => EE_Dependency_Map::load_from_cache,
78
-        'EventEspresso\core\services\request\Request'                                                => EE_Dependency_Map::load_from_cache,
79
-        'EventEspresso\core\services\json\JsonDataNode'                                              => EE_Dependency_Map::load_from_cache,
80
-        'EventEspresso\core\domain\entities\routing\specifications\RouteMatchSpecificationInterface' => EE_Dependency_Map::load_from_cache,
81
-    ];
82
-
83
-
84
-    /**
85
-     * Route constructor.
86
-     *
87
-     * @param EE_Dependency_Map                $dependency_map
88
-     * @param LoaderInterface                  $loader
89
-     * @param RequestInterface                 $request
90
-     * @param JsonDataNode                     $data_node
91
-     * @param RouteMatchSpecificationInterface $specification
92
-     */
93
-    public function __construct(
94
-        EE_Dependency_Map $dependency_map,
95
-        LoaderInterface $loader,
96
-        RequestInterface $request,
97
-        JsonDataNode $data_node = null,
98
-        RouteMatchSpecificationInterface $specification = null
99
-    ) {
100
-        $this->dependency_map = $dependency_map;
101
-        $this->data_node      = $data_node;
102
-        $this->loader         = $loader;
103
-        $this->request        = $request;
104
-        $this->specification  = $specification;
105
-    }
106
-
107
-
108
-    /**
109
-     * @since $VID:$
110
-     */
111
-    abstract protected function registerDependencies();
112
-
113
-
114
-    /**
115
-     * implements logic required to run during request
116
-     *
117
-     * @return bool
118
-     * @since   $VID:$
119
-     */
120
-    abstract protected function requestHandler();
121
-
122
-
123
-    /**
124
-     * @return array
125
-     */
126
-    public static function getDefaultDependencies()
127
-    {
128
-        return self::$default_dependencies;
129
-    }
130
-
131
-
132
-    /**
133
-     * @return array
134
-     */
135
-    public static function getFullDependencies()
136
-    {
137
-        return self::$full_dependencies;
138
-    }
139
-
140
-
141
-    /**
142
-     * @param JsonDataNode $data_node
143
-     */
144
-    protected function setDataNode($data_node)
145
-    {
146
-        $this->data_node = $data_node;
147
-    }
148
-
149
-
150
-    /**
151
-     * @param RouteMatchSpecificationInterface $specification
152
-     */
153
-    protected function setSpecification($specification)
154
-    {
155
-        $this->specification = $specification;
156
-    }
157
-
158
-
159
-    /**
160
-     * @return JsonDataNode
161
-     */
162
-    public function dataNode()
163
-    {
164
-        return $this->data_node;
165
-    }
166
-
167
-
168
-    /**
169
-     * runs route requestHandler() if
170
-     *      - route has not previously been handled
171
-     *      - route specification matches for current request
172
-     * sets route handled property based on results returned by requestHandler()
173
-     *
174
-     * @return bool
175
-     * @since   $VID:$
176
-     */
177
-    public function handleRequest()
178
-    {
179
-        if ($this->isNotHandled()) {
180
-            $this->initialize();
181
-            if ($this->matchesCurrentRequest()) {
182
-                do_action('AHEE__EventEspresso_core_domain_entities_routes_handlers_Route__handleRequest', $this);
183
-                $this->registerDependencies();
184
-                $handled = $this->requestHandler();
185
-                if (! is_bool($handled)) {
186
-                    throw new DomainException(
187
-                        esc_html__(
188
-                            'Route::requestHandler() must return a boolean to indicate whether the request has been handled or not.',
189
-                            'event_espresso'
190
-                        )
191
-                    );
192
-                }
193
-                $this->handled = filter_var($handled, FILTER_VALIDATE_BOOLEAN);
194
-            }
195
-        }
196
-        return $this->handled;
197
-    }
198
-
199
-
200
-    /**
201
-     * called just before matchesCurrentRequest()
202
-     * and allows Route to perform any setup required such as calling setSpecification()
203
-     *
204
-     * @since $VID:$
205
-     */
206
-    public function initialize()
207
-    {
208
-        // do nothing by default
209
-    }
210
-
211
-
212
-    /**
213
-     * @return bool
214
-     */
215
-    final public function isHandled()
216
-    {
217
-        return $this->handled;
218
-    }
219
-
220
-
221
-    /**
222
-     * @return bool
223
-     */
224
-    final public function isNotHandled()
225
-    {
226
-        return ! $this->handled;
227
-    }
228
-
229
-
230
-    /**
231
-     * returns true if the current request matches this route
232
-     * child classes can override and use Request directly to match route with request
233
-     * or supply a RouteMatchSpecification class and just use the below
234
-     *
235
-     * @return bool
236
-     * @since   $VID:$
237
-     */
238
-    public function matchesCurrentRequest()
239
-    {
240
-        return $this->specification instanceof RouteMatchSpecificationInterface
241
-            ? $this->specification->isMatchingRoute()
242
-            : false;
243
-    }
28
+	/**
29
+	 * @var AssetManagerInterface $asset_manager
30
+	 */
31
+	protected $asset_manager;
32
+
33
+	/**
34
+	 * @var EE_Dependency_Map $dependency_map
35
+	 */
36
+	protected $dependency_map;
37
+
38
+	/**
39
+	 * @var JsonDataNode $data_node
40
+	 */
41
+	protected $data_node;
42
+
43
+	/**
44
+	 * @var LoaderInterface $loader
45
+	 */
46
+	protected $loader;
47
+
48
+	/**
49
+	 * @var RequestInterface $request
50
+	 */
51
+	protected $request;
52
+
53
+	/**
54
+	 * @var RouteMatchSpecificationInterface $specification
55
+	 */
56
+	protected $specification;
57
+
58
+	/**
59
+	 * @var boolean $handled
60
+	 */
61
+	private $handled = false;
62
+
63
+	/**
64
+	 * @var array $default_dependencies
65
+	 */
66
+	protected static $default_dependencies = [
67
+		'EE_Dependency_Map'                           => EE_Dependency_Map::load_from_cache,
68
+		'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
69
+		'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
70
+	];
71
+
72
+	/**
73
+	 * @var array $full_dependencies
74
+	 */
75
+	protected static $full_dependencies = [
76
+		'EE_Dependency_Map'                                                                          => EE_Dependency_Map::load_from_cache,
77
+		'EventEspresso\core\services\loaders\Loader'                                                 => EE_Dependency_Map::load_from_cache,
78
+		'EventEspresso\core\services\request\Request'                                                => EE_Dependency_Map::load_from_cache,
79
+		'EventEspresso\core\services\json\JsonDataNode'                                              => EE_Dependency_Map::load_from_cache,
80
+		'EventEspresso\core\domain\entities\routing\specifications\RouteMatchSpecificationInterface' => EE_Dependency_Map::load_from_cache,
81
+	];
82
+
83
+
84
+	/**
85
+	 * Route constructor.
86
+	 *
87
+	 * @param EE_Dependency_Map                $dependency_map
88
+	 * @param LoaderInterface                  $loader
89
+	 * @param RequestInterface                 $request
90
+	 * @param JsonDataNode                     $data_node
91
+	 * @param RouteMatchSpecificationInterface $specification
92
+	 */
93
+	public function __construct(
94
+		EE_Dependency_Map $dependency_map,
95
+		LoaderInterface $loader,
96
+		RequestInterface $request,
97
+		JsonDataNode $data_node = null,
98
+		RouteMatchSpecificationInterface $specification = null
99
+	) {
100
+		$this->dependency_map = $dependency_map;
101
+		$this->data_node      = $data_node;
102
+		$this->loader         = $loader;
103
+		$this->request        = $request;
104
+		$this->specification  = $specification;
105
+	}
106
+
107
+
108
+	/**
109
+	 * @since $VID:$
110
+	 */
111
+	abstract protected function registerDependencies();
112
+
113
+
114
+	/**
115
+	 * implements logic required to run during request
116
+	 *
117
+	 * @return bool
118
+	 * @since   $VID:$
119
+	 */
120
+	abstract protected function requestHandler();
121
+
122
+
123
+	/**
124
+	 * @return array
125
+	 */
126
+	public static function getDefaultDependencies()
127
+	{
128
+		return self::$default_dependencies;
129
+	}
130
+
131
+
132
+	/**
133
+	 * @return array
134
+	 */
135
+	public static function getFullDependencies()
136
+	{
137
+		return self::$full_dependencies;
138
+	}
139
+
140
+
141
+	/**
142
+	 * @param JsonDataNode $data_node
143
+	 */
144
+	protected function setDataNode($data_node)
145
+	{
146
+		$this->data_node = $data_node;
147
+	}
148
+
149
+
150
+	/**
151
+	 * @param RouteMatchSpecificationInterface $specification
152
+	 */
153
+	protected function setSpecification($specification)
154
+	{
155
+		$this->specification = $specification;
156
+	}
157
+
158
+
159
+	/**
160
+	 * @return JsonDataNode
161
+	 */
162
+	public function dataNode()
163
+	{
164
+		return $this->data_node;
165
+	}
166
+
167
+
168
+	/**
169
+	 * runs route requestHandler() if
170
+	 *      - route has not previously been handled
171
+	 *      - route specification matches for current request
172
+	 * sets route handled property based on results returned by requestHandler()
173
+	 *
174
+	 * @return bool
175
+	 * @since   $VID:$
176
+	 */
177
+	public function handleRequest()
178
+	{
179
+		if ($this->isNotHandled()) {
180
+			$this->initialize();
181
+			if ($this->matchesCurrentRequest()) {
182
+				do_action('AHEE__EventEspresso_core_domain_entities_routes_handlers_Route__handleRequest', $this);
183
+				$this->registerDependencies();
184
+				$handled = $this->requestHandler();
185
+				if (! is_bool($handled)) {
186
+					throw new DomainException(
187
+						esc_html__(
188
+							'Route::requestHandler() must return a boolean to indicate whether the request has been handled or not.',
189
+							'event_espresso'
190
+						)
191
+					);
192
+				}
193
+				$this->handled = filter_var($handled, FILTER_VALIDATE_BOOLEAN);
194
+			}
195
+		}
196
+		return $this->handled;
197
+	}
198
+
199
+
200
+	/**
201
+	 * called just before matchesCurrentRequest()
202
+	 * and allows Route to perform any setup required such as calling setSpecification()
203
+	 *
204
+	 * @since $VID:$
205
+	 */
206
+	public function initialize()
207
+	{
208
+		// do nothing by default
209
+	}
210
+
211
+
212
+	/**
213
+	 * @return bool
214
+	 */
215
+	final public function isHandled()
216
+	{
217
+		return $this->handled;
218
+	}
219
+
220
+
221
+	/**
222
+	 * @return bool
223
+	 */
224
+	final public function isNotHandled()
225
+	{
226
+		return ! $this->handled;
227
+	}
228
+
229
+
230
+	/**
231
+	 * returns true if the current request matches this route
232
+	 * child classes can override and use Request directly to match route with request
233
+	 * or supply a RouteMatchSpecification class and just use the below
234
+	 *
235
+	 * @return bool
236
+	 * @since   $VID:$
237
+	 */
238
+	public function matchesCurrentRequest()
239
+	{
240
+		return $this->specification instanceof RouteMatchSpecificationInterface
241
+			? $this->specification->isMatchingRoute()
242
+			: false;
243
+	}
244 244
 }
Please login to merge, or discard this patch.
core/services/routing/Router.php 1 patch
Indentation   +196 added lines, -196 removed lines patch added patch discarded remove patch
@@ -15,200 +15,200 @@
 block discarded – undo
15 15
 class Router
16 16
 {
17 17
 
18
-    /**
19
-     * @var EE_Dependency_Map $dependency_map
20
-     */
21
-    protected $dependency_map;
22
-
23
-    /**
24
-     * @var LoaderInterface $loader
25
-     */
26
-    protected $loader;
27
-
28
-    /**
29
-     * @var RouteHandler $route_handler
30
-     */
31
-    protected $route_handler;
32
-
33
-    /**
34
-     * @var string $route_request_type
35
-     */
36
-    protected $route_request_type;
37
-
38
-
39
-    /**
40
-     * RoutingSwitch constructor.
41
-     *
42
-     * @param EE_Dependency_Map $dependency_map
43
-     * @param LoaderInterface   $loader
44
-     * @param RouteHandler      $router
45
-     */
46
-    public function __construct(EE_Dependency_Map $dependency_map, LoaderInterface $loader, RouteHandler $router)
47
-    {
48
-        $this->dependency_map = $dependency_map;
49
-        $this->loader         = $loader;
50
-        $this->route_handler  = $router;
51
-    }
52
-
53
-
54
-    /**
55
-     * @throws Exception
56
-     */
57
-    public function loadPrimaryRoutes()
58
-    {
59
-        $this->dependency_map->registerDependencies(
60
-            'EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests',
61
-            Route::getFullDependencies()
62
-        );
63
-        $this->dependency_map->registerDependencies(
64
-            'EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests',
65
-            Route::getFullDependencies()
66
-        );
67
-        // now load and prep all primary Routes
68
-        $this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests');
69
-        $this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests');
70
-        $this->route_request_type = $this->route_handler->getRouteRequestType();
71
-    }
72
-
73
-
74
-    /**
75
-     *
76
-     * @throws Exception
77
-     */
78
-    public function registerShortcodesModulesAndWidgets()
79
-    {
80
-        switch ($this->route_request_type) {
81
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
82
-                break;
83
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
84
-                $this->route_handler->addRoute(
85
-                    'EventEspresso\core\domain\entities\routing\handlers\frontend\ShortcodeRequests'
86
-                );
87
-                break;
88
-        }
89
-    }
90
-
91
-
92
-    /**
93
-     *
94
-     * @throws Exception
95
-     * @throws Exception
96
-     * @throws Exception
97
-     * @throws Exception
98
-     */
99
-    public function brewEspresso()
100
-    {
101
-        switch ($this->route_request_type) {
102
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
103
-                $this->route_handler->addRoute(
104
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\PueRequests'
105
-                );
106
-                break;
107
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
108
-                $this->route_handler->addRoute(
109
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\GQLRequests'
110
-                );
111
-                $this->route_handler->addRoute(
112
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\PueRequests'
113
-                );
114
-                $this->route_handler->addRoute(
115
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\RestApiRequests'
116
-                );
117
-                break;
118
-        }
119
-    }
120
-
121
-
122
-    /**
123
-     *
124
-     * @throws Exception
125
-     * @throws Exception
126
-     * @throws Exception
127
-     * @throws Exception
128
-     * @throws Exception
129
-     * @throws Exception
130
-     * @throws Exception
131
-     * @throws Exception
132
-     * @throws Exception
133
-     * @throws Exception
134
-     */
135
-    public function loadControllers()
136
-    {
137
-        switch ($this->route_request_type) {
138
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
139
-                $this->route_handler->addRoute(
140
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute'
141
-                );
142
-                $this->route_handler->addRoute(
143
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
144
-                );
145
-                break;
146
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
147
-                $this->route_handler->addRoute(
148
-                    'EventEspresso\core\domain\entities\routing\handlers\frontend\FrontendRequests'
149
-                );
150
-                $this->route_handler->addRoute(
151
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute'
152
-                );
153
-                $this->route_handler->addRoute(
154
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoLegacyAdmin'
155
-                );
156
-                $this->route_handler->addRoute(
157
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventsAdmin'
158
-                );
159
-                $this->route_handler->addRoute(
160
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventEditor'
161
-                );
162
-                $this->route_handler->addRoute(
163
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\GutenbergEditor'
164
-                );
165
-                $this->route_handler->addRoute(
166
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
167
-                );
168
-                $this->route_handler->addRoute(
169
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\WordPressHeartbeat'
170
-                );
171
-                break;
172
-        }
173
-    }
174
-
175
-
176
-    /**
177
-     *
178
-     * @throws Exception
179
-     * @throws Exception
180
-     */
181
-    public function coreLoadedAndReady()
182
-    {
183
-        switch ($this->route_request_type) {
184
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
185
-                break;
186
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
187
-                $this->route_handler->addRoute(
188
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\AssetRequests'
189
-                );
190
-                $this->route_handler->addRoute(
191
-                    'EventEspresso\core\domain\entities\routing\handlers\shared\SessionRequests'
192
-                );
193
-                break;
194
-        }
195
-    }
196
-
197
-
198
-    /**
199
-     *
200
-     * @throws Exception
201
-     */
202
-    public function initializeLast()
203
-    {
204
-        switch ($this->route_request_type) {
205
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
206
-                break;
207
-            case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
208
-                $this->route_handler->addRoute(
209
-                    'EventEspresso\core\domain\entities\routing\handlers\admin\PersonalDataRequests'
210
-                );
211
-                break;
212
-        }
213
-    }
18
+	/**
19
+	 * @var EE_Dependency_Map $dependency_map
20
+	 */
21
+	protected $dependency_map;
22
+
23
+	/**
24
+	 * @var LoaderInterface $loader
25
+	 */
26
+	protected $loader;
27
+
28
+	/**
29
+	 * @var RouteHandler $route_handler
30
+	 */
31
+	protected $route_handler;
32
+
33
+	/**
34
+	 * @var string $route_request_type
35
+	 */
36
+	protected $route_request_type;
37
+
38
+
39
+	/**
40
+	 * RoutingSwitch constructor.
41
+	 *
42
+	 * @param EE_Dependency_Map $dependency_map
43
+	 * @param LoaderInterface   $loader
44
+	 * @param RouteHandler      $router
45
+	 */
46
+	public function __construct(EE_Dependency_Map $dependency_map, LoaderInterface $loader, RouteHandler $router)
47
+	{
48
+		$this->dependency_map = $dependency_map;
49
+		$this->loader         = $loader;
50
+		$this->route_handler  = $router;
51
+	}
52
+
53
+
54
+	/**
55
+	 * @throws Exception
56
+	 */
57
+	public function loadPrimaryRoutes()
58
+	{
59
+		$this->dependency_map->registerDependencies(
60
+			'EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests',
61
+			Route::getFullDependencies()
62
+		);
63
+		$this->dependency_map->registerDependencies(
64
+			'EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests',
65
+			Route::getFullDependencies()
66
+		);
67
+		// now load and prep all primary Routes
68
+		$this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\admin\ActivationRequests');
69
+		$this->route_handler->addRoute('EventEspresso\core\domain\entities\routing\handlers\shared\RegularRequests');
70
+		$this->route_request_type = $this->route_handler->getRouteRequestType();
71
+	}
72
+
73
+
74
+	/**
75
+	 *
76
+	 * @throws Exception
77
+	 */
78
+	public function registerShortcodesModulesAndWidgets()
79
+	{
80
+		switch ($this->route_request_type) {
81
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
82
+				break;
83
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
84
+				$this->route_handler->addRoute(
85
+					'EventEspresso\core\domain\entities\routing\handlers\frontend\ShortcodeRequests'
86
+				);
87
+				break;
88
+		}
89
+	}
90
+
91
+
92
+	/**
93
+	 *
94
+	 * @throws Exception
95
+	 * @throws Exception
96
+	 * @throws Exception
97
+	 * @throws Exception
98
+	 */
99
+	public function brewEspresso()
100
+	{
101
+		switch ($this->route_request_type) {
102
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
103
+				$this->route_handler->addRoute(
104
+					'EventEspresso\core\domain\entities\routing\handlers\admin\PueRequests'
105
+				);
106
+				break;
107
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
108
+				$this->route_handler->addRoute(
109
+					'EventEspresso\core\domain\entities\routing\handlers\shared\GQLRequests'
110
+				);
111
+				$this->route_handler->addRoute(
112
+					'EventEspresso\core\domain\entities\routing\handlers\admin\PueRequests'
113
+				);
114
+				$this->route_handler->addRoute(
115
+					'EventEspresso\core\domain\entities\routing\handlers\shared\RestApiRequests'
116
+				);
117
+				break;
118
+		}
119
+	}
120
+
121
+
122
+	/**
123
+	 *
124
+	 * @throws Exception
125
+	 * @throws Exception
126
+	 * @throws Exception
127
+	 * @throws Exception
128
+	 * @throws Exception
129
+	 * @throws Exception
130
+	 * @throws Exception
131
+	 * @throws Exception
132
+	 * @throws Exception
133
+	 * @throws Exception
134
+	 */
135
+	public function loadControllers()
136
+	{
137
+		switch ($this->route_request_type) {
138
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
139
+				$this->route_handler->addRoute(
140
+					'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute'
141
+				);
142
+				$this->route_handler->addRoute(
143
+					'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
144
+				);
145
+				break;
146
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
147
+				$this->route_handler->addRoute(
148
+					'EventEspresso\core\domain\entities\routing\handlers\frontend\FrontendRequests'
149
+				);
150
+				$this->route_handler->addRoute(
151
+					'EventEspresso\core\domain\entities\routing\handlers\admin\AdminRoute'
152
+				);
153
+				$this->route_handler->addRoute(
154
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoLegacyAdmin'
155
+				);
156
+				$this->route_handler->addRoute(
157
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventsAdmin'
158
+				);
159
+				$this->route_handler->addRoute(
160
+					'EventEspresso\core\domain\entities\routing\handlers\admin\EspressoEventEditor'
161
+				);
162
+				$this->route_handler->addRoute(
163
+					'EventEspresso\core\domain\entities\routing\handlers\admin\GutenbergEditor'
164
+				);
165
+				$this->route_handler->addRoute(
166
+					'EventEspresso\core\domain\entities\routing\handlers\admin\WordPressPluginsPage'
167
+				);
168
+				$this->route_handler->addRoute(
169
+					'EventEspresso\core\domain\entities\routing\handlers\shared\WordPressHeartbeat'
170
+				);
171
+				break;
172
+		}
173
+	}
174
+
175
+
176
+	/**
177
+	 *
178
+	 * @throws Exception
179
+	 * @throws Exception
180
+	 */
181
+	public function coreLoadedAndReady()
182
+	{
183
+		switch ($this->route_request_type) {
184
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
185
+				break;
186
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
187
+				$this->route_handler->addRoute(
188
+					'EventEspresso\core\domain\entities\routing\handlers\shared\AssetRequests'
189
+				);
190
+				$this->route_handler->addRoute(
191
+					'EventEspresso\core\domain\entities\routing\handlers\shared\SessionRequests'
192
+				);
193
+				break;
194
+		}
195
+	}
196
+
197
+
198
+	/**
199
+	 *
200
+	 * @throws Exception
201
+	 */
202
+	public function initializeLast()
203
+	{
204
+		switch ($this->route_request_type) {
205
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_ACTIVATION:
206
+				break;
207
+			case PrimaryRoute::ROUTE_REQUEST_TYPE_REGULAR:
208
+				$this->route_handler->addRoute(
209
+					'EventEspresso\core\domain\entities\routing\handlers\admin\PersonalDataRequests'
210
+				);
211
+				break;
212
+		}
213
+	}
214 214
 }
Please login to merge, or discard this patch.
core/services/container/Mirror.php 1 patch
Indentation   +243 added lines, -243 removed lines patch added patch discarded remove patch
@@ -21,247 +21,247 @@
 block discarded – undo
21 21
 class Mirror
22 22
 {
23 23
 
24
-    /**
25
-     * @var ReflectionClass[] $classes
26
-     */
27
-    private $classes = array();
28
-
29
-    /**
30
-     * @var ReflectionMethod[] $constructors
31
-     */
32
-    private $constructors = array();
33
-
34
-    /**
35
-     * @var ReflectionParameter[][] $parameters
36
-     */
37
-    private $parameters = array();
38
-
39
-    /**
40
-     * @var ReflectionParameter[][] $parameters
41
-     */
42
-    private $parameter_classes = array();
43
-
44
-    /**
45
-     * @var ReflectionProperty[][] $properties
46
-     */
47
-    private $properties = array();
48
-
49
-    /**
50
-     * @var ReflectionMethod[][] $methods
51
-     */
52
-    private $methods = array();
53
-
54
-
55
-    /**
56
-     * @param string $class_name
57
-     * @return ReflectionClass
58
-     * @throws ReflectionException
59
-     * @throws InvalidDataTypeException
60
-     */
61
-    public function getReflectionClass($class_name)
62
-    {
63
-        if (! is_string($class_name)) {
64
-            throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
65
-        }
66
-        if (! isset($this->classes[ $class_name ])) {
67
-            $this->classes[ $class_name ] = new ReflectionClass($class_name);
68
-        }
69
-        return $this->classes[ $class_name ];
70
-    }
71
-
72
-
73
-    /**
74
-     * @param string $class_name
75
-     * @return ReflectionMethod
76
-     * @throws InvalidDataTypeException
77
-     * @throws ReflectionException
78
-     */
79
-    public function getConstructor($class_name)
80
-    {
81
-        if (! is_string($class_name)) {
82
-            throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
83
-        }
84
-        if (! isset($this->constructors[ $class_name ])) {
85
-            $reflection_class                  = $this->getReflectionClass($class_name);
86
-            $this->constructors[ $class_name ] = $reflection_class->getConstructor();
87
-        }
88
-        return $this->constructors[ $class_name ];
89
-    }
90
-
91
-
92
-    /**
93
-     * @param ReflectionClass $reflection_class
94
-     * @return ReflectionMethod
95
-     * @throws InvalidDataTypeException
96
-     * @throws ReflectionException
97
-     */
98
-    public function getConstructorFromReflection(ReflectionClass $reflection_class)
99
-    {
100
-        return $this->getConstructor($reflection_class->getName());
101
-    }
102
-
103
-
104
-    /**
105
-     * @param string $class_name
106
-     * @return ReflectionParameter[]
107
-     * @throws InvalidDataTypeException
108
-     * @throws ReflectionException
109
-     */
110
-    public function getParameters($class_name)
111
-    {
112
-        if (! isset($this->parameters[ $class_name ])) {
113
-            $constructor                     = $this->getConstructor($class_name);
114
-            $this->parameters[ $class_name ] = $constructor->getParameters();
115
-        }
116
-        return $this->parameters[ $class_name ];
117
-    }
118
-
119
-
120
-    /**
121
-     * @param ReflectionClass $reflection_class
122
-     * @return ReflectionParameter[]
123
-     * @throws InvalidDataTypeException
124
-     * @throws ReflectionException
125
-     */
126
-    public function getParametersFromReflection(ReflectionClass $reflection_class)
127
-    {
128
-        return $this->getParameters($reflection_class->getName());
129
-    }
130
-
131
-
132
-    /**
133
-     * @param ReflectionMethod $constructor
134
-     * @return ReflectionParameter[]
135
-     * @throws InvalidDataTypeException
136
-     * @throws ReflectionException
137
-     */
138
-    public function getParametersFromReflectionConstructor(ReflectionMethod $constructor)
139
-    {
140
-        return $this->getParameters($constructor->getDeclaringClass());
141
-    }
142
-
143
-
144
-    /**
145
-     * returns array of ReflectionParameter objects for parameters that are NOT optional
146
-     *
147
-     * @param string $class_name
148
-     * @return ReflectionParameter[]
149
-     * @throws InvalidDataTypeException
150
-     * @throws ReflectionException
151
-     */
152
-    public function getRequiredParameters($class_name)
153
-    {
154
-        $required_parameters = [];
155
-        $parameters = $this->getParameters($class_name);
156
-        foreach ($parameters as $parameter) {
157
-            if ($parameter instanceof ReflectionParameter && ! $parameter->isOptional()) {
158
-                $required_parameters[] = $parameter;
159
-            }
160
-        }
161
-        return $required_parameters;
162
-    }
163
-
164
-
165
-    /**
166
-     * @param ReflectionParameter $param
167
-     * @param string              $class_name
168
-     * @param string              $index
169
-     * @return string|null
170
-     */
171
-    public function getParameterClassName(ReflectionParameter $param, $class_name, $index)
172
-    {
173
-        if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_name'])) {
174
-            return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
175
-        }
176
-        if (! isset($this->parameter_classes[ $class_name ])) {
177
-            $this->parameter_classes[ $class_name ] = array();
178
-        }
179
-        if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
180
-            $this->parameter_classes[ $class_name ][ $index ] = array();
181
-        }
182
-        $this->parameter_classes[ $class_name ][ $index ]['param_class_name'] = $param->getClass()
183
-            ? $param->getClass()->name
184
-            : null;
185
-        return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
186
-    }
187
-
188
-
189
-    /**
190
-     * @param ReflectionParameter $param
191
-     * @param string              $class_name
192
-     * @param string              $index
193
-     * @return string|null
194
-     */
195
-    public function getParameterDefaultValue(ReflectionParameter $param, $class_name, $index)
196
-    {
197
-        if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_default'])) {
198
-            return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
199
-        }
200
-        if (! isset($this->parameter_classes[ $class_name ])) {
201
-            $this->parameter_classes[ $class_name ] = array();
202
-        }
203
-        if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
204
-            $this->parameter_classes[ $class_name ][ $index ] = array();
205
-        }
206
-        $this->parameter_classes[ $class_name ][ $index ]['param_class_default'] = $param->isDefaultValueAvailable()
207
-            ? $param->getDefaultValue()
208
-            : null;
209
-        return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
210
-    }
211
-
212
-
213
-    /**
214
-     * @param string $class_name
215
-     * @return ReflectionProperty[]
216
-     * @throws InvalidDataTypeException
217
-     * @throws ReflectionException
218
-     */
219
-    public function getProperties($class_name)
220
-    {
221
-        if (! isset($this->properties[ $class_name ])) {
222
-            $reflection_class                = $this->getReflectionClass($class_name);
223
-            $this->properties[ $class_name ] = $reflection_class->getProperties();
224
-        }
225
-        return $this->properties[ $class_name ];
226
-    }
227
-
228
-
229
-    /**
230
-     * @param ReflectionClass $reflection_class
231
-     * @return ReflectionProperty[]
232
-     * @throws InvalidDataTypeException
233
-     * @throws ReflectionException
234
-     */
235
-    public function getPropertiesFromReflection(ReflectionClass $reflection_class)
236
-    {
237
-        return $this->getProperties($reflection_class->getName());
238
-    }
239
-
240
-
241
-    /**
242
-     * @param string $class_name
243
-     * @return ReflectionMethod[]
244
-     * @throws InvalidDataTypeException
245
-     * @throws ReflectionException
246
-     */
247
-    public function getMethods($class_name)
248
-    {
249
-        if (! isset($this->methods[ $class_name ])) {
250
-            $reflection_class             = $this->getReflectionClass($class_name);
251
-            $this->methods[ $class_name ] = $reflection_class->getMethods();
252
-        }
253
-        return $this->methods[ $class_name ];
254
-    }
255
-
256
-
257
-    /**
258
-     * @param ReflectionClass $reflection_class )
259
-     * @return ReflectionMethod[]
260
-     * @throws InvalidDataTypeException
261
-     * @throws ReflectionException
262
-     */
263
-    public function getMethodsFromReflection(ReflectionClass $reflection_class)
264
-    {
265
-        return $this->getMethods($reflection_class->getName());
266
-    }
24
+	/**
25
+	 * @var ReflectionClass[] $classes
26
+	 */
27
+	private $classes = array();
28
+
29
+	/**
30
+	 * @var ReflectionMethod[] $constructors
31
+	 */
32
+	private $constructors = array();
33
+
34
+	/**
35
+	 * @var ReflectionParameter[][] $parameters
36
+	 */
37
+	private $parameters = array();
38
+
39
+	/**
40
+	 * @var ReflectionParameter[][] $parameters
41
+	 */
42
+	private $parameter_classes = array();
43
+
44
+	/**
45
+	 * @var ReflectionProperty[][] $properties
46
+	 */
47
+	private $properties = array();
48
+
49
+	/**
50
+	 * @var ReflectionMethod[][] $methods
51
+	 */
52
+	private $methods = array();
53
+
54
+
55
+	/**
56
+	 * @param string $class_name
57
+	 * @return ReflectionClass
58
+	 * @throws ReflectionException
59
+	 * @throws InvalidDataTypeException
60
+	 */
61
+	public function getReflectionClass($class_name)
62
+	{
63
+		if (! is_string($class_name)) {
64
+			throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
65
+		}
66
+		if (! isset($this->classes[ $class_name ])) {
67
+			$this->classes[ $class_name ] = new ReflectionClass($class_name);
68
+		}
69
+		return $this->classes[ $class_name ];
70
+	}
71
+
72
+
73
+	/**
74
+	 * @param string $class_name
75
+	 * @return ReflectionMethod
76
+	 * @throws InvalidDataTypeException
77
+	 * @throws ReflectionException
78
+	 */
79
+	public function getConstructor($class_name)
80
+	{
81
+		if (! is_string($class_name)) {
82
+			throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
83
+		}
84
+		if (! isset($this->constructors[ $class_name ])) {
85
+			$reflection_class                  = $this->getReflectionClass($class_name);
86
+			$this->constructors[ $class_name ] = $reflection_class->getConstructor();
87
+		}
88
+		return $this->constructors[ $class_name ];
89
+	}
90
+
91
+
92
+	/**
93
+	 * @param ReflectionClass $reflection_class
94
+	 * @return ReflectionMethod
95
+	 * @throws InvalidDataTypeException
96
+	 * @throws ReflectionException
97
+	 */
98
+	public function getConstructorFromReflection(ReflectionClass $reflection_class)
99
+	{
100
+		return $this->getConstructor($reflection_class->getName());
101
+	}
102
+
103
+
104
+	/**
105
+	 * @param string $class_name
106
+	 * @return ReflectionParameter[]
107
+	 * @throws InvalidDataTypeException
108
+	 * @throws ReflectionException
109
+	 */
110
+	public function getParameters($class_name)
111
+	{
112
+		if (! isset($this->parameters[ $class_name ])) {
113
+			$constructor                     = $this->getConstructor($class_name);
114
+			$this->parameters[ $class_name ] = $constructor->getParameters();
115
+		}
116
+		return $this->parameters[ $class_name ];
117
+	}
118
+
119
+
120
+	/**
121
+	 * @param ReflectionClass $reflection_class
122
+	 * @return ReflectionParameter[]
123
+	 * @throws InvalidDataTypeException
124
+	 * @throws ReflectionException
125
+	 */
126
+	public function getParametersFromReflection(ReflectionClass $reflection_class)
127
+	{
128
+		return $this->getParameters($reflection_class->getName());
129
+	}
130
+
131
+
132
+	/**
133
+	 * @param ReflectionMethod $constructor
134
+	 * @return ReflectionParameter[]
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws ReflectionException
137
+	 */
138
+	public function getParametersFromReflectionConstructor(ReflectionMethod $constructor)
139
+	{
140
+		return $this->getParameters($constructor->getDeclaringClass());
141
+	}
142
+
143
+
144
+	/**
145
+	 * returns array of ReflectionParameter objects for parameters that are NOT optional
146
+	 *
147
+	 * @param string $class_name
148
+	 * @return ReflectionParameter[]
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws ReflectionException
151
+	 */
152
+	public function getRequiredParameters($class_name)
153
+	{
154
+		$required_parameters = [];
155
+		$parameters = $this->getParameters($class_name);
156
+		foreach ($parameters as $parameter) {
157
+			if ($parameter instanceof ReflectionParameter && ! $parameter->isOptional()) {
158
+				$required_parameters[] = $parameter;
159
+			}
160
+		}
161
+		return $required_parameters;
162
+	}
163
+
164
+
165
+	/**
166
+	 * @param ReflectionParameter $param
167
+	 * @param string              $class_name
168
+	 * @param string              $index
169
+	 * @return string|null
170
+	 */
171
+	public function getParameterClassName(ReflectionParameter $param, $class_name, $index)
172
+	{
173
+		if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_name'])) {
174
+			return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
175
+		}
176
+		if (! isset($this->parameter_classes[ $class_name ])) {
177
+			$this->parameter_classes[ $class_name ] = array();
178
+		}
179
+		if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
180
+			$this->parameter_classes[ $class_name ][ $index ] = array();
181
+		}
182
+		$this->parameter_classes[ $class_name ][ $index ]['param_class_name'] = $param->getClass()
183
+			? $param->getClass()->name
184
+			: null;
185
+		return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
186
+	}
187
+
188
+
189
+	/**
190
+	 * @param ReflectionParameter $param
191
+	 * @param string              $class_name
192
+	 * @param string              $index
193
+	 * @return string|null
194
+	 */
195
+	public function getParameterDefaultValue(ReflectionParameter $param, $class_name, $index)
196
+	{
197
+		if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_default'])) {
198
+			return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
199
+		}
200
+		if (! isset($this->parameter_classes[ $class_name ])) {
201
+			$this->parameter_classes[ $class_name ] = array();
202
+		}
203
+		if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
204
+			$this->parameter_classes[ $class_name ][ $index ] = array();
205
+		}
206
+		$this->parameter_classes[ $class_name ][ $index ]['param_class_default'] = $param->isDefaultValueAvailable()
207
+			? $param->getDefaultValue()
208
+			: null;
209
+		return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
210
+	}
211
+
212
+
213
+	/**
214
+	 * @param string $class_name
215
+	 * @return ReflectionProperty[]
216
+	 * @throws InvalidDataTypeException
217
+	 * @throws ReflectionException
218
+	 */
219
+	public function getProperties($class_name)
220
+	{
221
+		if (! isset($this->properties[ $class_name ])) {
222
+			$reflection_class                = $this->getReflectionClass($class_name);
223
+			$this->properties[ $class_name ] = $reflection_class->getProperties();
224
+		}
225
+		return $this->properties[ $class_name ];
226
+	}
227
+
228
+
229
+	/**
230
+	 * @param ReflectionClass $reflection_class
231
+	 * @return ReflectionProperty[]
232
+	 * @throws InvalidDataTypeException
233
+	 * @throws ReflectionException
234
+	 */
235
+	public function getPropertiesFromReflection(ReflectionClass $reflection_class)
236
+	{
237
+		return $this->getProperties($reflection_class->getName());
238
+	}
239
+
240
+
241
+	/**
242
+	 * @param string $class_name
243
+	 * @return ReflectionMethod[]
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws ReflectionException
246
+	 */
247
+	public function getMethods($class_name)
248
+	{
249
+		if (! isset($this->methods[ $class_name ])) {
250
+			$reflection_class             = $this->getReflectionClass($class_name);
251
+			$this->methods[ $class_name ] = $reflection_class->getMethods();
252
+		}
253
+		return $this->methods[ $class_name ];
254
+	}
255
+
256
+
257
+	/**
258
+	 * @param ReflectionClass $reflection_class )
259
+	 * @return ReflectionMethod[]
260
+	 * @throws InvalidDataTypeException
261
+	 * @throws ReflectionException
262
+	 */
263
+	public function getMethodsFromReflection(ReflectionClass $reflection_class)
264
+	{
265
+		return $this->getMethods($reflection_class->getName());
266
+	}
267 267
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Debug_Tools.helper.php 2 patches
Indentation   +686 added lines, -686 removed lines patch added patch discarded remove patch
@@ -11,677 +11,677 @@  discard block
 block discarded – undo
11 11
 class EEH_Debug_Tools
12 12
 {
13 13
 
14
-    /**
15
-     *    instance of the EEH_Autoloader object
16
-     *
17
-     * @var    $_instance
18
-     * @access    private
19
-     */
20
-    private static $_instance;
21
-
22
-    /**
23
-     * @var array
24
-     */
25
-    protected $_memory_usage_points = array();
26
-
27
-
28
-
29
-    /**
30
-     * @singleton method used to instantiate class object
31
-     * @access    public
32
-     * @return EEH_Debug_Tools
33
-     */
34
-    public static function instance()
35
-    {
36
-        // check if class object is instantiated, and instantiated properly
37
-        if (! self::$_instance instanceof EEH_Debug_Tools) {
38
-            self::$_instance = new self();
39
-        }
40
-        return self::$_instance;
41
-    }
42
-
43
-
44
-
45
-    /**
46
-     * private class constructor
47
-     */
48
-    private function __construct()
49
-    {
50
-        // load Kint PHP debugging library
51
-        if (! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php')) {
52
-            // despite EE4 having a check for an existing copy of the Kint debugging class,
53
-            // if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
54
-            // then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
55
-            // so we've moved it to our test folder so that it is not included with production releases
56
-            // plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
57
-            require_once(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php');
58
-        }
59
-        // if ( ! defined('DOING_AJAX') || $_REQUEST['noheader'] !== 'true' || ! isset( $_REQUEST['noheader'], $_REQUEST['TB_iframe'] ) ) {
60
-        // add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
61
-        // }
62
-        $plugin = basename(EE_PLUGIN_DIR_PATH);
63
-        add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
64
-        add_action('activated_plugin', array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
65
-        add_action('shutdown', array('EEH_Debug_Tools', 'show_db_name'));
66
-    }
67
-
68
-
69
-
70
-    /**
71
-     *    show_db_name
72
-     *
73
-     * @return void
74
-     */
75
-    public static function show_db_name()
76
-    {
77
-        if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
78
-            echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
79
-                 . DB_NAME
80
-                 . '</p>';
81
-        }
82
-        if (EE_DEBUG) {
83
-            Benchmark::displayResults();
84
-        }
85
-    }
86
-
87
-
88
-
89
-    /**
90
-     *    dump EE_Session object at bottom of page after everything else has happened
91
-     *
92
-     * @return void
93
-     */
94
-    public function espresso_session_footer_dump()
95
-    {
96
-        if ((defined('WP_DEBUG') && WP_DEBUG)
97
-            && ! defined('DOING_AJAX')
98
-            && class_exists('Kint')
99
-            && function_exists('wp_get_current_user')
100
-            && current_user_can('update_core')
101
-            && class_exists('EE_Registry')
102
-        ) {
103
-            Kint::dump(EE_Registry::instance()->SSN->id());
104
-            Kint::dump(EE_Registry::instance()->SSN);
105
-            //          Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
106
-            $this->espresso_list_hooked_functions();
107
-            Benchmark::displayResults();
108
-        }
109
-    }
110
-
111
-
112
-
113
-    /**
114
-     *    List All Hooked Functions
115
-     *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
116
-     *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
117
-     *
118
-     * @param string $tag
119
-     * @return void
120
-     */
121
-    public function espresso_list_hooked_functions($tag = '')
122
-    {
123
-        global $wp_filter;
124
-        echo '<br/><br/><br/><h3>Hooked Functions</h3>';
125
-        if ($tag) {
126
-            $hook[ $tag ] = $wp_filter[ $tag ];
127
-            if (! is_array($hook[ $tag ])) {
128
-                trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
129
-                return;
130
-            }
131
-            echo '<h5>For Tag: ' . $tag . '</h5>';
132
-        } else {
133
-            $hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
134
-            ksort($hook);
135
-        }
136
-        foreach ($hook as $tag_name => $priorities) {
137
-            echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>$tag_name</strong><br />";
138
-            ksort($priorities);
139
-            foreach ($priorities as $priority => $function) {
140
-                echo $priority;
141
-                foreach ($function as $name => $properties) {
142
-                    echo "\t$name<br />";
143
-                }
144
-            }
145
-        }
146
-    }
147
-
148
-
149
-
150
-    /**
151
-     *    registered_filter_callbacks
152
-     *
153
-     * @param string $hook_name
154
-     * @return array
155
-     */
156
-    public static function registered_filter_callbacks($hook_name = '')
157
-    {
158
-        $filters = array();
159
-        global $wp_filter;
160
-        if (isset($wp_filter[ $hook_name ])) {
161
-            $filters[ $hook_name ] = array();
162
-            foreach ($wp_filter[ $hook_name ] as $priority => $callbacks) {
163
-                $filters[ $hook_name ][ $priority ] = array();
164
-                foreach ($callbacks as $callback) {
165
-                    $filters[ $hook_name ][ $priority ][] = $callback['function'];
166
-                }
167
-            }
168
-        }
169
-        return $filters;
170
-    }
171
-
172
-
173
-
174
-    /**
175
-     *    captures plugin activation errors for debugging
176
-     *
177
-     * @return void
178
-     * @throws EE_Error
179
-     */
180
-    public static function ee_plugin_activation_errors()
181
-    {
182
-        if (WP_DEBUG) {
183
-            $activation_errors = ob_get_contents();
184
-            if (empty($activation_errors)) {
185
-                return;
186
-            }
187
-            $activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
188
-            espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
189
-            if (class_exists('EEH_File')) {
190
-                try {
191
-                    EEH_File::ensure_file_exists_and_is_writable(
192
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html'
193
-                    );
194
-                    EEH_File::write_to_file(
195
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
196
-                        $activation_errors
197
-                    );
198
-                } catch (EE_Error $e) {
199
-                    EE_Error::add_error(
200
-                        sprintf(
201
-                            __(
202
-                                'The Event Espresso activation errors file could not be setup because: %s',
203
-                                'event_espresso'
204
-                            ),
205
-                            $e->getMessage()
206
-                        ),
207
-                        __FILE__,
208
-                        __FUNCTION__,
209
-                        __LINE__
210
-                    );
211
-                }
212
-            } else {
213
-                // old school attempt
214
-                file_put_contents(
215
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
216
-                    $activation_errors
217
-                );
218
-            }
219
-            $activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
220
-            update_option('ee_plugin_activation_errors', $activation_errors);
221
-        }
222
-    }
223
-
224
-
225
-
226
-    /**
227
-     * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.
228
-     * Very useful for providing helpful messages to developers when the method of doing something has been deprecated,
229
-     * or we want to make sure they use something the right way.
230
-     *
231
-     * @access public
232
-     * @param string $function      The function that was called
233
-     * @param string $message       A message explaining what has been done incorrectly
234
-     * @param string $version       The version of Event Espresso where the error was added
235
-     * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
236
-     *                              for a deprecated function. This allows deprecation to occur during one version,
237
-     *                              but not have any notices appear until a later version. This allows developers
238
-     *                              extra time to update their code before notices appear.
239
-     * @param int    $error_type
240
-     * @uses   trigger_error()
241
-     */
242
-    public function doing_it_wrong(
243
-        $function,
244
-        $message,
245
-        $version,
246
-        $applies_when = '',
247
-        $error_type = null
248
-    ) {
249
-        $applies_when = ! empty($applies_when) ? $applies_when : espresso_version();
250
-        $error_type = $error_type !== null ? $error_type : E_USER_NOTICE;
251
-        // because we swapped the parameter order around for the last two params,
252
-        // let's verify that some third party isn't still passing an error type value for the third param
253
-        if (is_int($applies_when)) {
254
-            $error_type = $applies_when;
255
-            $applies_when = espresso_version();
256
-        }
257
-        // if not displaying notices yet, then just leave
258
-        if (version_compare(espresso_version(), $applies_when, '<')) {
259
-            return;
260
-        }
261
-        do_action('AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
262
-        $version = $version === null
263
-            ? ''
264
-            : sprintf(
265
-                __('(This message was added in version %s of Event Espresso)', 'event_espresso'),
266
-                $version
267
-            );
268
-        $error_message = sprintf(
269
-            esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s', 'event_espresso'),
270
-            $function,
271
-            '<strong>',
272
-            '</strong>',
273
-            $message,
274
-            $version
275
-        );
276
-        // don't trigger error if doing ajax,
277
-        // instead we'll add a transient EE_Error notice that in theory should show on the next request.
278
-        if (defined('DOING_AJAX') && DOING_AJAX) {
279
-            $error_message .= ' ' . esc_html__(
280
-                'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
281
-                'event_espresso'
282
-            );
283
-            $error_message .= '<ul><li>';
284
-            $error_message .= implode('</li><li>', EE_Registry::instance()->REQ->params());
285
-            $error_message .= '</ul>';
286
-            EE_Error::add_error($error_message, 'debug::doing_it_wrong', $function, '42');
287
-            // now we set this on the transient so it shows up on the next request.
288
-            EE_Error::get_notices(false, true);
289
-        } else {
290
-            trigger_error($error_message, $error_type);
291
-        }
292
-    }
293
-
294
-
295
-
296
-
297
-    /**
298
-     * Logger helpers
299
-     */
300
-    /**
301
-     * debug
302
-     *
303
-     * @param string $class
304
-     * @param string $func
305
-     * @param string $line
306
-     * @param array  $info
307
-     * @param bool   $display_request
308
-     * @param string $debug_index
309
-     * @param string $debug_key
310
-     * @throws EE_Error
311
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
312
-     */
313
-    public static function log(
314
-        $class = '',
315
-        $func = '',
316
-        $line = '',
317
-        $info = array(),
318
-        $display_request = false,
319
-        $debug_index = '',
320
-        $debug_key = 'EE_DEBUG_SPCO'
321
-    ) {
322
-        if (WP_DEBUG) {
323
-            $debug_key = $debug_key . '_' . EE_Session::instance()->id();
324
-            $debug_data = get_option($debug_key, array());
325
-            $default_data = array(
326
-                $class => $func . '() : ' . $line,
327
-                'REQ'  => $display_request ? $_REQUEST : '',
328
-            );
329
-            // don't serialize objects
330
-            $info = self::strip_objects($info);
331
-            $index = ! empty($debug_index) ? $debug_index : 0;
332
-            if (! isset($debug_data[ $index ])) {
333
-                $debug_data[ $index ] = array();
334
-            }
335
-            $debug_data[ $index ][ microtime() ] = array_merge($default_data, $info);
336
-            update_option($debug_key, $debug_data);
337
-        }
338
-    }
339
-
340
-
341
-
342
-    /**
343
-     * strip_objects
344
-     *
345
-     * @param array $info
346
-     * @return array
347
-     */
348
-    public static function strip_objects($info = array())
349
-    {
350
-        foreach ($info as $key => $value) {
351
-            if (is_array($value)) {
352
-                $info[ $key ] = self::strip_objects($value);
353
-            } elseif (is_object($value)) {
354
-                $object_class = get_class($value);
355
-                $info[ $object_class ] = array();
356
-                $info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
357
-                if (method_exists($value, 'ID')) {
358
-                    $info[ $object_class ]['ID'] = $value->ID();
359
-                }
360
-                if (method_exists($value, 'status')) {
361
-                    $info[ $object_class ]['status'] = $value->status();
362
-                } elseif (method_exists($value, 'status_ID')) {
363
-                    $info[ $object_class ]['status'] = $value->status_ID();
364
-                }
365
-                unset($info[ $key ]);
366
-            }
367
-        }
368
-        return (array) $info;
369
-    }
370
-
371
-
372
-
373
-    /**
374
-     * @param mixed      $var
375
-     * @param string     $var_name
376
-     * @param string     $file
377
-     * @param int|string $line
378
-     * @param int|string $heading_tag
379
-     * @param bool       $die
380
-     * @param string     $margin
381
-     */
382
-    public static function printv(
383
-        $var,
384
-        $var_name = '',
385
-        $file = '',
386
-        $line = '',
387
-        $heading_tag = 5,
388
-        $die = false,
389
-        $margin = ''
390
-    ) {
391
-        $var_name = ! $var_name ? 'string' : $var_name;
392
-        $var_name = ucwords(str_replace('$', '', $var_name));
393
-        $is_method = method_exists($var_name, $var);
394
-        $var_name = ucwords(str_replace('_', ' ', $var_name));
395
-        $heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
396
-        $result = EEH_Debug_Tools::headingSpacer($heading_tag);
397
-        $result .= EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
398
-        $result .= $is_method
399
-            ? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
400
-            : EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
401
-        $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
402
-        $result .= EEH_Debug_Tools::headingX($heading_tag);
403
-        if ($die) {
404
-            die($result);
405
-        }
406
-        echo $result;
407
-    }
408
-
409
-
410
-    protected static function headingTag($heading_tag)
411
-    {
412
-        $heading_tag = absint($heading_tag);
413
-        return $heading_tag > 0 && $heading_tag < 7 ? "h{$heading_tag}" : 'h5';
414
-    }
415
-
416
-
417
-    protected static function headingSpacer($heading_tag)
418
-    {
419
-        return EEH_Debug_Tools::plainOutput() && ($heading_tag === 'h1' || $heading_tag === 'h2')
420
-            ? "\n"
421
-            : '';
422
-    }
423
-
424
-
425
-    protected static function plainOutput()
426
-    {
427
-        return defined('EE_TESTS_DIR')
428
-               || (defined('DOING_AJAX') && DOING_AJAX)
429
-               || (
430
-                   isset($_SERVER['REQUEST_URI'])
431
-                   && strpos(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), 'wp-json') !== false
432
-               );
433
-    }
434
-
435
-
436
-    /**
437
-     * @param string $var_name
438
-     * @param string $heading_tag
439
-     * @param string $margin
440
-     * @param int    $line
441
-     * @return string
442
-     */
443
-    protected static function heading($var_name = '', $heading_tag = 'h5', $margin = '', $line = 0)
444
-    {
445
-        if (EEH_Debug_Tools::plainOutput()) {
446
-            $heading = '';
447
-            if ($heading_tag === 'h1' || $heading_tag === 'h2') {
448
-                $heading .= "\n";
449
-            }
450
-            $heading .= "\n{$line}) {$var_name}";
451
-            return $heading;
452
-        }
453
-        $margin = "25px 0 0 {$margin}";
454
-        return '<' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . ';"><b>' . $var_name . '</b>';
455
-    }
456
-
457
-
458
-
459
-    /**
460
-     * @param string $heading_tag
461
-     * @return string
462
-     */
463
-    protected static function headingX($heading_tag = 'h5')
464
-    {
465
-        if (EEH_Debug_Tools::plainOutput()) {
466
-            return '';
467
-        }
468
-        return '</' . $heading_tag . '>';
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     * @param string $content
475
-     * @return string
476
-     */
477
-    protected static function grey_span($content = '')
478
-    {
479
-        if (EEH_Debug_Tools::plainOutput()) {
480
-            return $content;
481
-        }
482
-        return '<span style="color:#999">' . $content . '</span>';
483
-    }
484
-
485
-
486
-
487
-    /**
488
-     * @param string $file
489
-     * @param int    $line
490
-     * @return string
491
-     */
492
-    protected static function file_and_line($file, $line, $heading_tag)
493
-    {
494
-        if ($file === '' || $line === '') {
495
-            return '';
496
-        }
497
-        $file = str_replace(EE_PLUGIN_DIR_PATH, '/', $file);
498
-        if (EEH_Debug_Tools::plainOutput()) {
499
-            if ($heading_tag === 'h1' || $heading_tag === 'h2') {
500
-                return " ({$file})";
501
-            }
502
-            return '';
503
-        }
504
-        return '<br /><span style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;">'
505
-               . $file
506
-               . '<br />line no: '
507
-               . $line
508
-               . '</span>';
509
-    }
510
-
511
-
512
-
513
-    /**
514
-     * @param string $content
515
-     * @return string
516
-     */
517
-    protected static function orange_span($content = '')
518
-    {
519
-        if (EEH_Debug_Tools::plainOutput()) {
520
-            return $content;
521
-        }
522
-        return '<span style="color:#E76700">' . $content . '</span>';
523
-    }
524
-
525
-
526
-
527
-    /**
528
-     * @param mixed $var
529
-     * @return string
530
-     */
531
-    protected static function pre_span($var)
532
-    {
533
-        ob_start();
534
-        var_dump($var);
535
-        $var = ob_get_clean();
536
-        if (EEH_Debug_Tools::plainOutput()) {
537
-            return $var;
538
-        }
539
-        return '<pre style="color:#999; padding:1em; background: #fff">' . $var . '</pre>';
540
-    }
541
-
542
-
543
-
544
-    /**
545
-     * @param mixed      $var
546
-     * @param string     $var_name
547
-     * @param string     $file
548
-     * @param int|string $line
549
-     * @param int|string $heading_tag
550
-     * @param bool       $die
551
-     */
552
-    public static function printr(
553
-        $var,
554
-        $var_name = '',
555
-        $file = '',
556
-        $line = '',
557
-        $heading_tag = 5,
558
-        $die = false
559
-    ) {
560
-        // return;
561
-        $file = str_replace(rtrim(ABSPATH, '\\/'), '', $file);
562
-        if (empty($var) && empty($var_name)) {
563
-            $var = $file;
564
-            $var_name = "line $line";
565
-            $file = '';
566
-            $line = '';
567
-        }
568
-        $margin = is_admin() ? ' 180px' : '0';
569
-        // $print_r = false;
570
-        if (is_string($var)) {
571
-            EEH_Debug_Tools::printv($var, $var_name, $file, $line, $heading_tag, $die, $margin);
572
-            return;
573
-        }
574
-        if (is_object($var)) {
575
-            $var_name = ! $var_name ? 'object' : $var_name;
576
-            // $print_r = true;
577
-        } elseif (is_array($var)) {
578
-            $var_name = ! $var_name ? 'array' : $var_name;
579
-            // $print_r = true;
580
-        } elseif (is_numeric($var)) {
581
-            $var_name = ! $var_name ? 'numeric' : $var_name;
582
-        } elseif ($var === null) {
583
-            $var_name = ! $var_name ? 'null' : $var_name;
584
-        }
585
-        $var_name = ucwords(str_replace(array('$', '_'), array('', ' '), $var_name));
586
-        $heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
587
-        $result = EEH_Debug_Tools::headingSpacer($heading_tag);
588
-        $result .= EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
589
-        $result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
590
-            EEH_Debug_Tools::pre_span($var)
591
-        );
592
-        $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
593
-        $result .= EEH_Debug_Tools::headingX($heading_tag);
594
-        if ($die) {
595
-            die($result);
596
-        }
597
-        echo $result;
598
-    }
599
-
600
-
601
-
602
-    /******************** deprecated ********************/
603
-
604
-
605
-
606
-    /**
607
-     * @deprecated 4.9.39.rc.034
608
-     */
609
-    public function reset_times()
610
-    {
611
-        Benchmark::resetTimes();
612
-    }
613
-
614
-
615
-
616
-    /**
617
-     * @deprecated 4.9.39.rc.034
618
-     * @param null $timer_name
619
-     */
620
-    public function start_timer($timer_name = null)
621
-    {
622
-        Benchmark::startTimer($timer_name);
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @deprecated 4.9.39.rc.034
629
-     * @param string $timer_name
630
-     */
631
-    public function stop_timer($timer_name = '')
632
-    {
633
-        Benchmark::stopTimer($timer_name);
634
-    }
635
-
636
-
637
-
638
-    /**
639
-     * @deprecated 4.9.39.rc.034
640
-     * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
641
-     * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
642
-     * @return void
643
-     */
644
-    public function measure_memory($label, $output_now = false)
645
-    {
646
-        Benchmark::measureMemory($label, $output_now);
647
-    }
648
-
649
-
650
-
651
-    /**
652
-     * @deprecated 4.9.39.rc.034
653
-     * @param int $size
654
-     * @return string
655
-     */
656
-    public function convert($size)
657
-    {
658
-        return Benchmark::convert($size);
659
-    }
660
-
661
-
662
-
663
-    /**
664
-     * @deprecated 4.9.39.rc.034
665
-     * @param bool $output_now
666
-     * @return string
667
-     */
668
-    public function show_times($output_now = true)
669
-    {
670
-        return Benchmark::displayResults($output_now);
671
-    }
672
-
673
-
674
-
675
-    /**
676
-     * @deprecated 4.9.39.rc.034
677
-     * @param string $timer_name
678
-     * @param float  $total_time
679
-     * @return string
680
-     */
681
-    public function format_time($timer_name, $total_time)
682
-    {
683
-        return Benchmark::formatTime($timer_name, $total_time);
684
-    }
14
+	/**
15
+	 *    instance of the EEH_Autoloader object
16
+	 *
17
+	 * @var    $_instance
18
+	 * @access    private
19
+	 */
20
+	private static $_instance;
21
+
22
+	/**
23
+	 * @var array
24
+	 */
25
+	protected $_memory_usage_points = array();
26
+
27
+
28
+
29
+	/**
30
+	 * @singleton method used to instantiate class object
31
+	 * @access    public
32
+	 * @return EEH_Debug_Tools
33
+	 */
34
+	public static function instance()
35
+	{
36
+		// check if class object is instantiated, and instantiated properly
37
+		if (! self::$_instance instanceof EEH_Debug_Tools) {
38
+			self::$_instance = new self();
39
+		}
40
+		return self::$_instance;
41
+	}
42
+
43
+
44
+
45
+	/**
46
+	 * private class constructor
47
+	 */
48
+	private function __construct()
49
+	{
50
+		// load Kint PHP debugging library
51
+		if (! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php')) {
52
+			// despite EE4 having a check for an existing copy of the Kint debugging class,
53
+			// if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
54
+			// then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
55
+			// so we've moved it to our test folder so that it is not included with production releases
56
+			// plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
57
+			require_once(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php');
58
+		}
59
+		// if ( ! defined('DOING_AJAX') || $_REQUEST['noheader'] !== 'true' || ! isset( $_REQUEST['noheader'], $_REQUEST['TB_iframe'] ) ) {
60
+		// add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
61
+		// }
62
+		$plugin = basename(EE_PLUGIN_DIR_PATH);
63
+		add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
64
+		add_action('activated_plugin', array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
65
+		add_action('shutdown', array('EEH_Debug_Tools', 'show_db_name'));
66
+	}
67
+
68
+
69
+
70
+	/**
71
+	 *    show_db_name
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public static function show_db_name()
76
+	{
77
+		if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
78
+			echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
79
+				 . DB_NAME
80
+				 . '</p>';
81
+		}
82
+		if (EE_DEBUG) {
83
+			Benchmark::displayResults();
84
+		}
85
+	}
86
+
87
+
88
+
89
+	/**
90
+	 *    dump EE_Session object at bottom of page after everything else has happened
91
+	 *
92
+	 * @return void
93
+	 */
94
+	public function espresso_session_footer_dump()
95
+	{
96
+		if ((defined('WP_DEBUG') && WP_DEBUG)
97
+			&& ! defined('DOING_AJAX')
98
+			&& class_exists('Kint')
99
+			&& function_exists('wp_get_current_user')
100
+			&& current_user_can('update_core')
101
+			&& class_exists('EE_Registry')
102
+		) {
103
+			Kint::dump(EE_Registry::instance()->SSN->id());
104
+			Kint::dump(EE_Registry::instance()->SSN);
105
+			//          Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
106
+			$this->espresso_list_hooked_functions();
107
+			Benchmark::displayResults();
108
+		}
109
+	}
110
+
111
+
112
+
113
+	/**
114
+	 *    List All Hooked Functions
115
+	 *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
116
+	 *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
117
+	 *
118
+	 * @param string $tag
119
+	 * @return void
120
+	 */
121
+	public function espresso_list_hooked_functions($tag = '')
122
+	{
123
+		global $wp_filter;
124
+		echo '<br/><br/><br/><h3>Hooked Functions</h3>';
125
+		if ($tag) {
126
+			$hook[ $tag ] = $wp_filter[ $tag ];
127
+			if (! is_array($hook[ $tag ])) {
128
+				trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
129
+				return;
130
+			}
131
+			echo '<h5>For Tag: ' . $tag . '</h5>';
132
+		} else {
133
+			$hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
134
+			ksort($hook);
135
+		}
136
+		foreach ($hook as $tag_name => $priorities) {
137
+			echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>$tag_name</strong><br />";
138
+			ksort($priorities);
139
+			foreach ($priorities as $priority => $function) {
140
+				echo $priority;
141
+				foreach ($function as $name => $properties) {
142
+					echo "\t$name<br />";
143
+				}
144
+			}
145
+		}
146
+	}
147
+
148
+
149
+
150
+	/**
151
+	 *    registered_filter_callbacks
152
+	 *
153
+	 * @param string $hook_name
154
+	 * @return array
155
+	 */
156
+	public static function registered_filter_callbacks($hook_name = '')
157
+	{
158
+		$filters = array();
159
+		global $wp_filter;
160
+		if (isset($wp_filter[ $hook_name ])) {
161
+			$filters[ $hook_name ] = array();
162
+			foreach ($wp_filter[ $hook_name ] as $priority => $callbacks) {
163
+				$filters[ $hook_name ][ $priority ] = array();
164
+				foreach ($callbacks as $callback) {
165
+					$filters[ $hook_name ][ $priority ][] = $callback['function'];
166
+				}
167
+			}
168
+		}
169
+		return $filters;
170
+	}
171
+
172
+
173
+
174
+	/**
175
+	 *    captures plugin activation errors for debugging
176
+	 *
177
+	 * @return void
178
+	 * @throws EE_Error
179
+	 */
180
+	public static function ee_plugin_activation_errors()
181
+	{
182
+		if (WP_DEBUG) {
183
+			$activation_errors = ob_get_contents();
184
+			if (empty($activation_errors)) {
185
+				return;
186
+			}
187
+			$activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
188
+			espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
189
+			if (class_exists('EEH_File')) {
190
+				try {
191
+					EEH_File::ensure_file_exists_and_is_writable(
192
+						EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html'
193
+					);
194
+					EEH_File::write_to_file(
195
+						EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
196
+						$activation_errors
197
+					);
198
+				} catch (EE_Error $e) {
199
+					EE_Error::add_error(
200
+						sprintf(
201
+							__(
202
+								'The Event Espresso activation errors file could not be setup because: %s',
203
+								'event_espresso'
204
+							),
205
+							$e->getMessage()
206
+						),
207
+						__FILE__,
208
+						__FUNCTION__,
209
+						__LINE__
210
+					);
211
+				}
212
+			} else {
213
+				// old school attempt
214
+				file_put_contents(
215
+					EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
216
+					$activation_errors
217
+				);
218
+			}
219
+			$activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
220
+			update_option('ee_plugin_activation_errors', $activation_errors);
221
+		}
222
+	}
223
+
224
+
225
+
226
+	/**
227
+	 * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.
228
+	 * Very useful for providing helpful messages to developers when the method of doing something has been deprecated,
229
+	 * or we want to make sure they use something the right way.
230
+	 *
231
+	 * @access public
232
+	 * @param string $function      The function that was called
233
+	 * @param string $message       A message explaining what has been done incorrectly
234
+	 * @param string $version       The version of Event Espresso where the error was added
235
+	 * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
236
+	 *                              for a deprecated function. This allows deprecation to occur during one version,
237
+	 *                              but not have any notices appear until a later version. This allows developers
238
+	 *                              extra time to update their code before notices appear.
239
+	 * @param int    $error_type
240
+	 * @uses   trigger_error()
241
+	 */
242
+	public function doing_it_wrong(
243
+		$function,
244
+		$message,
245
+		$version,
246
+		$applies_when = '',
247
+		$error_type = null
248
+	) {
249
+		$applies_when = ! empty($applies_when) ? $applies_when : espresso_version();
250
+		$error_type = $error_type !== null ? $error_type : E_USER_NOTICE;
251
+		// because we swapped the parameter order around for the last two params,
252
+		// let's verify that some third party isn't still passing an error type value for the third param
253
+		if (is_int($applies_when)) {
254
+			$error_type = $applies_when;
255
+			$applies_when = espresso_version();
256
+		}
257
+		// if not displaying notices yet, then just leave
258
+		if (version_compare(espresso_version(), $applies_when, '<')) {
259
+			return;
260
+		}
261
+		do_action('AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
262
+		$version = $version === null
263
+			? ''
264
+			: sprintf(
265
+				__('(This message was added in version %s of Event Espresso)', 'event_espresso'),
266
+				$version
267
+			);
268
+		$error_message = sprintf(
269
+			esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s', 'event_espresso'),
270
+			$function,
271
+			'<strong>',
272
+			'</strong>',
273
+			$message,
274
+			$version
275
+		);
276
+		// don't trigger error if doing ajax,
277
+		// instead we'll add a transient EE_Error notice that in theory should show on the next request.
278
+		if (defined('DOING_AJAX') && DOING_AJAX) {
279
+			$error_message .= ' ' . esc_html__(
280
+				'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
281
+				'event_espresso'
282
+			);
283
+			$error_message .= '<ul><li>';
284
+			$error_message .= implode('</li><li>', EE_Registry::instance()->REQ->params());
285
+			$error_message .= '</ul>';
286
+			EE_Error::add_error($error_message, 'debug::doing_it_wrong', $function, '42');
287
+			// now we set this on the transient so it shows up on the next request.
288
+			EE_Error::get_notices(false, true);
289
+		} else {
290
+			trigger_error($error_message, $error_type);
291
+		}
292
+	}
293
+
294
+
295
+
296
+
297
+	/**
298
+	 * Logger helpers
299
+	 */
300
+	/**
301
+	 * debug
302
+	 *
303
+	 * @param string $class
304
+	 * @param string $func
305
+	 * @param string $line
306
+	 * @param array  $info
307
+	 * @param bool   $display_request
308
+	 * @param string $debug_index
309
+	 * @param string $debug_key
310
+	 * @throws EE_Error
311
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
312
+	 */
313
+	public static function log(
314
+		$class = '',
315
+		$func = '',
316
+		$line = '',
317
+		$info = array(),
318
+		$display_request = false,
319
+		$debug_index = '',
320
+		$debug_key = 'EE_DEBUG_SPCO'
321
+	) {
322
+		if (WP_DEBUG) {
323
+			$debug_key = $debug_key . '_' . EE_Session::instance()->id();
324
+			$debug_data = get_option($debug_key, array());
325
+			$default_data = array(
326
+				$class => $func . '() : ' . $line,
327
+				'REQ'  => $display_request ? $_REQUEST : '',
328
+			);
329
+			// don't serialize objects
330
+			$info = self::strip_objects($info);
331
+			$index = ! empty($debug_index) ? $debug_index : 0;
332
+			if (! isset($debug_data[ $index ])) {
333
+				$debug_data[ $index ] = array();
334
+			}
335
+			$debug_data[ $index ][ microtime() ] = array_merge($default_data, $info);
336
+			update_option($debug_key, $debug_data);
337
+		}
338
+	}
339
+
340
+
341
+
342
+	/**
343
+	 * strip_objects
344
+	 *
345
+	 * @param array $info
346
+	 * @return array
347
+	 */
348
+	public static function strip_objects($info = array())
349
+	{
350
+		foreach ($info as $key => $value) {
351
+			if (is_array($value)) {
352
+				$info[ $key ] = self::strip_objects($value);
353
+			} elseif (is_object($value)) {
354
+				$object_class = get_class($value);
355
+				$info[ $object_class ] = array();
356
+				$info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
357
+				if (method_exists($value, 'ID')) {
358
+					$info[ $object_class ]['ID'] = $value->ID();
359
+				}
360
+				if (method_exists($value, 'status')) {
361
+					$info[ $object_class ]['status'] = $value->status();
362
+				} elseif (method_exists($value, 'status_ID')) {
363
+					$info[ $object_class ]['status'] = $value->status_ID();
364
+				}
365
+				unset($info[ $key ]);
366
+			}
367
+		}
368
+		return (array) $info;
369
+	}
370
+
371
+
372
+
373
+	/**
374
+	 * @param mixed      $var
375
+	 * @param string     $var_name
376
+	 * @param string     $file
377
+	 * @param int|string $line
378
+	 * @param int|string $heading_tag
379
+	 * @param bool       $die
380
+	 * @param string     $margin
381
+	 */
382
+	public static function printv(
383
+		$var,
384
+		$var_name = '',
385
+		$file = '',
386
+		$line = '',
387
+		$heading_tag = 5,
388
+		$die = false,
389
+		$margin = ''
390
+	) {
391
+		$var_name = ! $var_name ? 'string' : $var_name;
392
+		$var_name = ucwords(str_replace('$', '', $var_name));
393
+		$is_method = method_exists($var_name, $var);
394
+		$var_name = ucwords(str_replace('_', ' ', $var_name));
395
+		$heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
396
+		$result = EEH_Debug_Tools::headingSpacer($heading_tag);
397
+		$result .= EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
398
+		$result .= $is_method
399
+			? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
400
+			: EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
401
+		$result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
402
+		$result .= EEH_Debug_Tools::headingX($heading_tag);
403
+		if ($die) {
404
+			die($result);
405
+		}
406
+		echo $result;
407
+	}
408
+
409
+
410
+	protected static function headingTag($heading_tag)
411
+	{
412
+		$heading_tag = absint($heading_tag);
413
+		return $heading_tag > 0 && $heading_tag < 7 ? "h{$heading_tag}" : 'h5';
414
+	}
415
+
416
+
417
+	protected static function headingSpacer($heading_tag)
418
+	{
419
+		return EEH_Debug_Tools::plainOutput() && ($heading_tag === 'h1' || $heading_tag === 'h2')
420
+			? "\n"
421
+			: '';
422
+	}
423
+
424
+
425
+	protected static function plainOutput()
426
+	{
427
+		return defined('EE_TESTS_DIR')
428
+			   || (defined('DOING_AJAX') && DOING_AJAX)
429
+			   || (
430
+				   isset($_SERVER['REQUEST_URI'])
431
+				   && strpos(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), 'wp-json') !== false
432
+			   );
433
+	}
434
+
435
+
436
+	/**
437
+	 * @param string $var_name
438
+	 * @param string $heading_tag
439
+	 * @param string $margin
440
+	 * @param int    $line
441
+	 * @return string
442
+	 */
443
+	protected static function heading($var_name = '', $heading_tag = 'h5', $margin = '', $line = 0)
444
+	{
445
+		if (EEH_Debug_Tools::plainOutput()) {
446
+			$heading = '';
447
+			if ($heading_tag === 'h1' || $heading_tag === 'h2') {
448
+				$heading .= "\n";
449
+			}
450
+			$heading .= "\n{$line}) {$var_name}";
451
+			return $heading;
452
+		}
453
+		$margin = "25px 0 0 {$margin}";
454
+		return '<' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . ';"><b>' . $var_name . '</b>';
455
+	}
456
+
457
+
458
+
459
+	/**
460
+	 * @param string $heading_tag
461
+	 * @return string
462
+	 */
463
+	protected static function headingX($heading_tag = 'h5')
464
+	{
465
+		if (EEH_Debug_Tools::plainOutput()) {
466
+			return '';
467
+		}
468
+		return '</' . $heading_tag . '>';
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 * @param string $content
475
+	 * @return string
476
+	 */
477
+	protected static function grey_span($content = '')
478
+	{
479
+		if (EEH_Debug_Tools::plainOutput()) {
480
+			return $content;
481
+		}
482
+		return '<span style="color:#999">' . $content . '</span>';
483
+	}
484
+
485
+
486
+
487
+	/**
488
+	 * @param string $file
489
+	 * @param int    $line
490
+	 * @return string
491
+	 */
492
+	protected static function file_and_line($file, $line, $heading_tag)
493
+	{
494
+		if ($file === '' || $line === '') {
495
+			return '';
496
+		}
497
+		$file = str_replace(EE_PLUGIN_DIR_PATH, '/', $file);
498
+		if (EEH_Debug_Tools::plainOutput()) {
499
+			if ($heading_tag === 'h1' || $heading_tag === 'h2') {
500
+				return " ({$file})";
501
+			}
502
+			return '';
503
+		}
504
+		return '<br /><span style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;">'
505
+			   . $file
506
+			   . '<br />line no: '
507
+			   . $line
508
+			   . '</span>';
509
+	}
510
+
511
+
512
+
513
+	/**
514
+	 * @param string $content
515
+	 * @return string
516
+	 */
517
+	protected static function orange_span($content = '')
518
+	{
519
+		if (EEH_Debug_Tools::plainOutput()) {
520
+			return $content;
521
+		}
522
+		return '<span style="color:#E76700">' . $content . '</span>';
523
+	}
524
+
525
+
526
+
527
+	/**
528
+	 * @param mixed $var
529
+	 * @return string
530
+	 */
531
+	protected static function pre_span($var)
532
+	{
533
+		ob_start();
534
+		var_dump($var);
535
+		$var = ob_get_clean();
536
+		if (EEH_Debug_Tools::plainOutput()) {
537
+			return $var;
538
+		}
539
+		return '<pre style="color:#999; padding:1em; background: #fff">' . $var . '</pre>';
540
+	}
541
+
542
+
543
+
544
+	/**
545
+	 * @param mixed      $var
546
+	 * @param string     $var_name
547
+	 * @param string     $file
548
+	 * @param int|string $line
549
+	 * @param int|string $heading_tag
550
+	 * @param bool       $die
551
+	 */
552
+	public static function printr(
553
+		$var,
554
+		$var_name = '',
555
+		$file = '',
556
+		$line = '',
557
+		$heading_tag = 5,
558
+		$die = false
559
+	) {
560
+		// return;
561
+		$file = str_replace(rtrim(ABSPATH, '\\/'), '', $file);
562
+		if (empty($var) && empty($var_name)) {
563
+			$var = $file;
564
+			$var_name = "line $line";
565
+			$file = '';
566
+			$line = '';
567
+		}
568
+		$margin = is_admin() ? ' 180px' : '0';
569
+		// $print_r = false;
570
+		if (is_string($var)) {
571
+			EEH_Debug_Tools::printv($var, $var_name, $file, $line, $heading_tag, $die, $margin);
572
+			return;
573
+		}
574
+		if (is_object($var)) {
575
+			$var_name = ! $var_name ? 'object' : $var_name;
576
+			// $print_r = true;
577
+		} elseif (is_array($var)) {
578
+			$var_name = ! $var_name ? 'array' : $var_name;
579
+			// $print_r = true;
580
+		} elseif (is_numeric($var)) {
581
+			$var_name = ! $var_name ? 'numeric' : $var_name;
582
+		} elseif ($var === null) {
583
+			$var_name = ! $var_name ? 'null' : $var_name;
584
+		}
585
+		$var_name = ucwords(str_replace(array('$', '_'), array('', ' '), $var_name));
586
+		$heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
587
+		$result = EEH_Debug_Tools::headingSpacer($heading_tag);
588
+		$result .= EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
589
+		$result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
590
+			EEH_Debug_Tools::pre_span($var)
591
+		);
592
+		$result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
593
+		$result .= EEH_Debug_Tools::headingX($heading_tag);
594
+		if ($die) {
595
+			die($result);
596
+		}
597
+		echo $result;
598
+	}
599
+
600
+
601
+
602
+	/******************** deprecated ********************/
603
+
604
+
605
+
606
+	/**
607
+	 * @deprecated 4.9.39.rc.034
608
+	 */
609
+	public function reset_times()
610
+	{
611
+		Benchmark::resetTimes();
612
+	}
613
+
614
+
615
+
616
+	/**
617
+	 * @deprecated 4.9.39.rc.034
618
+	 * @param null $timer_name
619
+	 */
620
+	public function start_timer($timer_name = null)
621
+	{
622
+		Benchmark::startTimer($timer_name);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @deprecated 4.9.39.rc.034
629
+	 * @param string $timer_name
630
+	 */
631
+	public function stop_timer($timer_name = '')
632
+	{
633
+		Benchmark::stopTimer($timer_name);
634
+	}
635
+
636
+
637
+
638
+	/**
639
+	 * @deprecated 4.9.39.rc.034
640
+	 * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
641
+	 * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
642
+	 * @return void
643
+	 */
644
+	public function measure_memory($label, $output_now = false)
645
+	{
646
+		Benchmark::measureMemory($label, $output_now);
647
+	}
648
+
649
+
650
+
651
+	/**
652
+	 * @deprecated 4.9.39.rc.034
653
+	 * @param int $size
654
+	 * @return string
655
+	 */
656
+	public function convert($size)
657
+	{
658
+		return Benchmark::convert($size);
659
+	}
660
+
661
+
662
+
663
+	/**
664
+	 * @deprecated 4.9.39.rc.034
665
+	 * @param bool $output_now
666
+	 * @return string
667
+	 */
668
+	public function show_times($output_now = true)
669
+	{
670
+		return Benchmark::displayResults($output_now);
671
+	}
672
+
673
+
674
+
675
+	/**
676
+	 * @deprecated 4.9.39.rc.034
677
+	 * @param string $timer_name
678
+	 * @param float  $total_time
679
+	 * @return string
680
+	 */
681
+	public function format_time($timer_name, $total_time)
682
+	{
683
+		return Benchmark::formatTime($timer_name, $total_time);
684
+	}
685 685
 }
686 686
 
687 687
 
@@ -691,31 +691,31 @@  discard block
 block discarded – undo
691 691
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
692 692
  */
693 693
 if (class_exists('Kint') && ! function_exists('dump_wp_query')) {
694
-    function dump_wp_query()
695
-    {
696
-        global $wp_query;
697
-        d($wp_query);
698
-    }
694
+	function dump_wp_query()
695
+	{
696
+		global $wp_query;
697
+		d($wp_query);
698
+	}
699 699
 }
700 700
 /**
701 701
  * borrowed from Kint Debugger
702 702
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
703 703
  */
704 704
 if (class_exists('Kint') && ! function_exists('dump_wp')) {
705
-    function dump_wp()
706
-    {
707
-        global $wp;
708
-        d($wp);
709
-    }
705
+	function dump_wp()
706
+	{
707
+		global $wp;
708
+		d($wp);
709
+	}
710 710
 }
711 711
 /**
712 712
  * borrowed from Kint Debugger
713 713
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
714 714
  */
715 715
 if (class_exists('Kint') && ! function_exists('dump_post')) {
716
-    function dump_post()
717
-    {
718
-        global $post;
719
-        d($post);
720
-    }
716
+	function dump_post()
717
+	{
718
+		global $post;
719
+		d($post);
720
+	}
721 721
 }
Please login to merge, or discard this patch.
Spacing   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -34,7 +34,7 @@  discard block
 block discarded – undo
34 34
     public static function instance()
35 35
     {
36 36
         // check if class object is instantiated, and instantiated properly
37
-        if (! self::$_instance instanceof EEH_Debug_Tools) {
37
+        if ( ! self::$_instance instanceof EEH_Debug_Tools) {
38 38
             self::$_instance = new self();
39 39
         }
40 40
         return self::$_instance;
@@ -48,13 +48,13 @@  discard block
 block discarded – undo
48 48
     private function __construct()
49 49
     {
50 50
         // load Kint PHP debugging library
51
-        if (! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php')) {
51
+        if ( ! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH.'tests/kint/Kint.class.php')) {
52 52
             // despite EE4 having a check for an existing copy of the Kint debugging class,
53 53
             // if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
54 54
             // then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
55 55
             // so we've moved it to our test folder so that it is not included with production releases
56 56
             // plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
57
-            require_once(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php');
57
+            require_once(EE_PLUGIN_DIR_PATH.'tests/kint/Kint.class.php');
58 58
         }
59 59
         // if ( ! defined('DOING_AJAX') || $_REQUEST['noheader'] !== 'true' || ! isset( $_REQUEST['noheader'], $_REQUEST['TB_iframe'] ) ) {
60 60
         // add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
      */
75 75
     public static function show_db_name()
76 76
     {
77
-        if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
77
+        if ( ! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
78 78
             echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
79 79
                  . DB_NAME
80 80
                  . '</p>';
@@ -123,12 +123,12 @@  discard block
 block discarded – undo
123 123
         global $wp_filter;
124 124
         echo '<br/><br/><br/><h3>Hooked Functions</h3>';
125 125
         if ($tag) {
126
-            $hook[ $tag ] = $wp_filter[ $tag ];
127
-            if (! is_array($hook[ $tag ])) {
126
+            $hook[$tag] = $wp_filter[$tag];
127
+            if ( ! is_array($hook[$tag])) {
128 128
                 trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
129 129
                 return;
130 130
             }
131
-            echo '<h5>For Tag: ' . $tag . '</h5>';
131
+            echo '<h5>For Tag: '.$tag.'</h5>';
132 132
         } else {
133 133
             $hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
134 134
             ksort($hook);
@@ -157,12 +157,12 @@  discard block
 block discarded – undo
157 157
     {
158 158
         $filters = array();
159 159
         global $wp_filter;
160
-        if (isset($wp_filter[ $hook_name ])) {
161
-            $filters[ $hook_name ] = array();
162
-            foreach ($wp_filter[ $hook_name ] as $priority => $callbacks) {
163
-                $filters[ $hook_name ][ $priority ] = array();
160
+        if (isset($wp_filter[$hook_name])) {
161
+            $filters[$hook_name] = array();
162
+            foreach ($wp_filter[$hook_name] as $priority => $callbacks) {
163
+                $filters[$hook_name][$priority] = array();
164 164
                 foreach ($callbacks as $callback) {
165
-                    $filters[ $hook_name ][ $priority ][] = $callback['function'];
165
+                    $filters[$hook_name][$priority][] = $callback['function'];
166 166
                 }
167 167
             }
168 168
         }
@@ -184,15 +184,15 @@  discard block
 block discarded – undo
184 184
             if (empty($activation_errors)) {
185 185
                 return;
186 186
             }
187
-            $activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
188
-            espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
187
+            $activation_errors = date('Y-m-d H:i:s')."\n".$activation_errors;
188
+            espresso_load_required('EEH_File', EE_HELPERS.'EEH_File.helper.php');
189 189
             if (class_exists('EEH_File')) {
190 190
                 try {
191 191
                     EEH_File::ensure_file_exists_and_is_writable(
192
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html'
192
+                        EVENT_ESPRESSO_UPLOAD_DIR.'logs/espresso_plugin_activation_errors.html'
193 193
                     );
194 194
                     EEH_File::write_to_file(
195
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
195
+                        EVENT_ESPRESSO_UPLOAD_DIR.'logs/espresso_plugin_activation_errors.html',
196 196
                         $activation_errors
197 197
                     );
198 198
                 } catch (EE_Error $e) {
@@ -212,11 +212,11 @@  discard block
 block discarded – undo
212 212
             } else {
213 213
                 // old school attempt
214 214
                 file_put_contents(
215
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
215
+                    EVENT_ESPRESSO_UPLOAD_DIR.'logs/espresso_plugin_activation_errors.html',
216 216
                     $activation_errors
217 217
                 );
218 218
             }
219
-            $activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
219
+            $activation_errors = get_option('ee_plugin_activation_errors', '').$activation_errors;
220 220
             update_option('ee_plugin_activation_errors', $activation_errors);
221 221
         }
222 222
     }
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
         // don't trigger error if doing ajax,
277 277
         // instead we'll add a transient EE_Error notice that in theory should show on the next request.
278 278
         if (defined('DOING_AJAX') && DOING_AJAX) {
279
-            $error_message .= ' ' . esc_html__(
279
+            $error_message .= ' '.esc_html__(
280 280
                 'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
281 281
                 'event_espresso'
282 282
             );
@@ -320,19 +320,19 @@  discard block
 block discarded – undo
320 320
         $debug_key = 'EE_DEBUG_SPCO'
321 321
     ) {
322 322
         if (WP_DEBUG) {
323
-            $debug_key = $debug_key . '_' . EE_Session::instance()->id();
323
+            $debug_key = $debug_key.'_'.EE_Session::instance()->id();
324 324
             $debug_data = get_option($debug_key, array());
325 325
             $default_data = array(
326
-                $class => $func . '() : ' . $line,
326
+                $class => $func.'() : '.$line,
327 327
                 'REQ'  => $display_request ? $_REQUEST : '',
328 328
             );
329 329
             // don't serialize objects
330 330
             $info = self::strip_objects($info);
331 331
             $index = ! empty($debug_index) ? $debug_index : 0;
332
-            if (! isset($debug_data[ $index ])) {
333
-                $debug_data[ $index ] = array();
332
+            if ( ! isset($debug_data[$index])) {
333
+                $debug_data[$index] = array();
334 334
             }
335
-            $debug_data[ $index ][ microtime() ] = array_merge($default_data, $info);
335
+            $debug_data[$index][microtime()] = array_merge($default_data, $info);
336 336
             update_option($debug_key, $debug_data);
337 337
         }
338 338
     }
@@ -349,20 +349,20 @@  discard block
 block discarded – undo
349 349
     {
350 350
         foreach ($info as $key => $value) {
351 351
             if (is_array($value)) {
352
-                $info[ $key ] = self::strip_objects($value);
352
+                $info[$key] = self::strip_objects($value);
353 353
             } elseif (is_object($value)) {
354 354
                 $object_class = get_class($value);
355
-                $info[ $object_class ] = array();
356
-                $info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
355
+                $info[$object_class] = array();
356
+                $info[$object_class]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
357 357
                 if (method_exists($value, 'ID')) {
358
-                    $info[ $object_class ]['ID'] = $value->ID();
358
+                    $info[$object_class]['ID'] = $value->ID();
359 359
                 }
360 360
                 if (method_exists($value, 'status')) {
361
-                    $info[ $object_class ]['status'] = $value->status();
361
+                    $info[$object_class]['status'] = $value->status();
362 362
                 } elseif (method_exists($value, 'status_ID')) {
363
-                    $info[ $object_class ]['status'] = $value->status_ID();
363
+                    $info[$object_class]['status'] = $value->status_ID();
364 364
                 }
365
-                unset($info[ $key ]);
365
+                unset($info[$key]);
366 366
             }
367 367
         }
368 368
         return (array) $info;
@@ -396,8 +396,8 @@  discard block
 block discarded – undo
396 396
         $result = EEH_Debug_Tools::headingSpacer($heading_tag);
397 397
         $result .= EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
398 398
         $result .= $is_method
399
-            ? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
400
-            : EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
399
+            ? EEH_Debug_Tools::grey_span('::').EEH_Debug_Tools::orange_span($var.'()')
400
+            : EEH_Debug_Tools::grey_span(' : ').EEH_Debug_Tools::orange_span($var);
401 401
         $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
402 402
         $result .= EEH_Debug_Tools::headingX($heading_tag);
403 403
         if ($die) {
@@ -451,7 +451,7 @@  discard block
 block discarded – undo
451 451
             return $heading;
452 452
         }
453 453
         $margin = "25px 0 0 {$margin}";
454
-        return '<' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . ';"><b>' . $var_name . '</b>';
454
+        return '<'.$heading_tag.' style="color:#2EA2CC; margin:'.$margin.';"><b>'.$var_name.'</b>';
455 455
     }
456 456
 
457 457
 
@@ -465,7 +465,7 @@  discard block
 block discarded – undo
465 465
         if (EEH_Debug_Tools::plainOutput()) {
466 466
             return '';
467 467
         }
468
-        return '</' . $heading_tag . '>';
468
+        return '</'.$heading_tag.'>';
469 469
     }
470 470
 
471 471
 
@@ -479,7 +479,7 @@  discard block
 block discarded – undo
479 479
         if (EEH_Debug_Tools::plainOutput()) {
480 480
             return $content;
481 481
         }
482
-        return '<span style="color:#999">' . $content . '</span>';
482
+        return '<span style="color:#999">'.$content.'</span>';
483 483
     }
484 484
 
485 485
 
@@ -519,7 +519,7 @@  discard block
 block discarded – undo
519 519
         if (EEH_Debug_Tools::plainOutput()) {
520 520
             return $content;
521 521
         }
522
-        return '<span style="color:#E76700">' . $content . '</span>';
522
+        return '<span style="color:#E76700">'.$content.'</span>';
523 523
     }
524 524
 
525 525
 
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
         if (EEH_Debug_Tools::plainOutput()) {
537 537
             return $var;
538 538
         }
539
-        return '<pre style="color:#999; padding:1em; background: #fff">' . $var . '</pre>';
539
+        return '<pre style="color:#999; padding:1em; background: #fff">'.$var.'</pre>';
540 540
     }
541 541
 
542 542
 
@@ -586,7 +586,7 @@  discard block
 block discarded – undo
586 586
         $heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
587 587
         $result = EEH_Debug_Tools::headingSpacer($heading_tag);
588 588
         $result .= EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
589
-        $result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
589
+        $result .= EEH_Debug_Tools::grey_span(' : ').EEH_Debug_Tools::orange_span(
590 590
             EEH_Debug_Tools::pre_span($var)
591 591
         );
592 592
         $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
Please login to merge, or discard this patch.
core/helpers/EEH_File.helper.php 2 patches
Indentation   +901 added lines, -901 removed lines patch added patch discarded remove patch
@@ -25,905 +25,905 @@
 block discarded – undo
25 25
 class EEH_File extends EEH_Base implements EEHI_File
26 26
 {
27 27
 
28
-    /**
29
-     * @var string $_credentials_form
30
-     */
31
-    private static $_credentials_form;
32
-
33
-    /**
34
-     * @var WP_Filesystem_Base $_wp_filesystem
35
-     */
36
-    protected static $_wp_filesystem;
37
-
38
-
39
-    /**
40
-     * @param string|null $filepath the filepath we want to work in. If its in the
41
-     *                              wp uploads directory, we'll want to just use the filesystem directly.
42
-     *                              If not provided, we have to assume its not in the uploads directory
43
-     * @return WP_Filesystem_Base
44
-     */
45
-    private static function _get_wp_filesystem($filepath = null)
46
-    {
47
-        if (apply_filters(
48
-            'FHEE__EEH_File___get_wp_filesystem__allow_using_filesystem_direct',
49
-            $filepath && EEH_File::is_in_uploads_folder($filepath),
50
-            $filepath
51
-        )) {
52
-            return EEH_File::loadAlternateWpFileSystem();
53
-        }
54
-        return EEH_File::loadWpFileSystem();
55
-    }
56
-
57
-
58
-    /**
59
-     * @return WP_Filesystem_Base
60
-     */
61
-    private static function loadAlternateWpFileSystem()
62
-    {
63
-        if (! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
64
-            require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
65
-            $method             = 'direct';
66
-            $wp_filesystem_file =
67
-                apply_filters(
68
-                    'filesystem_method_file',
69
-                    ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php',
70
-                    $method
71
-                );
72
-            // added the following validation logic
73
-            // because we allow the filesystem filepath to be filtered,
74
-            // and are loading whatever file the path pointed to,
75
-            // but we were not validating things in any way :scream_emoji:
76
-            $valid_wp_filesystem_types = [
77
-                'direct'     => 'WP_Filesystem_Direct',
78
-                'ftpext'     => 'WP_Filesystem_FTPext',
79
-                'ftpsockets' => 'WP_Filesystem_ftpsockets',
80
-                'ssh2'       => 'WP_Filesystem_SSH2',
81
-            ];
82
-            $valid                     = false;
83
-            $wp_filesystem_class       = '';
84
-            foreach ($valid_wp_filesystem_types as $method => $filesystem_class) {
85
-                // if file path matches for one of valid types, then toggle $valid to true
86
-                if (strpos($wp_filesystem_file, $method) > 0) {
87
-                    $valid               = true;
88
-                    $wp_filesystem_class = $filesystem_class;
89
-                }
90
-            }
91
-            if (! $valid || ! file_exists($wp_filesystem_file)) {
92
-                EE_Error::add_error(
93
-                    sprintf(
94
-                        __(
95
-                            'The supplied WP Filesystem filepath "%1$s" is either missing or invalid.',
96
-                            'event_espresso'
97
-                        ),
98
-                        $wp_filesystem_file
99
-                    ),
100
-                    __FILE__,
101
-                    __FUNCTION__,
102
-                    __LINE__
103
-                );
104
-            }
105
-            // check constants defined, just like in the wp-admin/includes/file.php WP_Filesystem()
106
-            if (! defined('FS_CHMOD_DIR')) {
107
-                define('FS_CHMOD_DIR', (fileperms(ABSPATH) & 0775 | 0755));
108
-            }
109
-            if (! defined('FS_CHMOD_FILE')) {
110
-                define('FS_CHMOD_FILE', (fileperms(ABSPATH . 'index.php') & 0775 | 0644));
111
-            }
112
-            require_once($wp_filesystem_file);
113
-            EEH_File::$_wp_filesystem = new $wp_filesystem_class([]);
114
-        }
115
-        return EEH_File::$_wp_filesystem;
116
-    }
117
-
118
-
119
-    /**
120
-     * @return WP_Filesystem_Base
121
-     */
122
-    private static function loadWpFileSystem()
123
-    {
124
-        global $wp_filesystem;
125
-        // no filesystem setup ???
126
-        if (! $wp_filesystem instanceof WP_Filesystem_Base) {
127
-            // if some eager beaver's just trying to get in there too early...
128
-            // let them do it, because we are one of those eager beavers! :P
129
-            /**
130
-             * more explanations are probably merited. http://codex.wordpress.org/Filesystem_API#Initializing_WP_Filesystem_Base
131
-             * says WP_Filesystem should be used after 'wp_loaded', but currently EE's activation process
132
-             * is setup to mostly happen on 'init', and refactoring to have it happen on
133
-             * 'wp_loaded' is too much work on a BETA milestone.
134
-             * So this fix is expected to work if the WP files are owned by the server user,
135
-             * but probably not if the user needs to enter their FTP credentials to modify files
136
-             * and there may be troubles if the WP files are owned by a different user
137
-             * than the server user. But both of these issues should exist in 4.4 and earlier too
138
-             */
139
-            if (false && ! did_action('wp_loaded')) {
140
-                $msg =
141
-                    __(
142
-                        'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
143
-                        'event_espresso'
144
-                    );
145
-                if (WP_DEBUG) {
146
-                    $msg .= '<br />' . __(
147
-                        'The WP Filesystem can not be accessed until after the "wp_loaded" hook has run, so it\'s best not to attempt access until the "admin_init" hookpoint.',
148
-                        'event_espresso'
149
-                    );
150
-                }
151
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
152
-            }
153
-            // should be loaded if we are past the wp_loaded hook...
154
-            if (! function_exists('WP_Filesystem')) {
155
-                require_once(ABSPATH . 'wp-admin/includes/file.php');
156
-                require_once(ABSPATH . 'wp-admin/includes/template.php');
157
-            }
158
-            // turn on output buffering so that we can capture the credentials form
159
-            ob_start();
160
-            $credentials = request_filesystem_credentials(false);
161
-            // store credentials form for the time being
162
-            EEH_File::$_credentials_form = ob_get_clean();
163
-            // if credentials do NOT exist
164
-            if ($credentials === false) {
165
-                add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
166
-                EE_Error::add_error(
167
-                    __(
168
-                        'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
169
-                        'event_espresso'
170
-                    ),
171
-                    __FILE__,
172
-                    __FUNCTION__,
173
-                    __LINE__
174
-                );
175
-            }
176
-            // basically check for direct or previously configured access
177
-            if (! WP_Filesystem($credentials)
178
-                && is_wp_error($wp_filesystem->errors)
179
-                && $wp_filesystem->errors->get_error_code()
180
-            ) {
181
-                add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
182
-                EE_Error::add_error(
183
-                    sprintf(
184
-                        __('WP Filesystem Error: $1%s', 'event_espresso'),
185
-                        $wp_filesystem->errors->get_error_message()
186
-                    ),
187
-                    __FILE__,
188
-                    __FUNCTION__,
189
-                    __LINE__
190
-                );
191
-            }
192
-        }
193
-        return $wp_filesystem;
194
-    }
195
-
196
-
197
-    /**
198
-     * display_request_filesystem_credentials_form
199
-     */
200
-    public static function display_request_filesystem_credentials_form()
201
-    {
202
-        if (! empty(EEH_File::$_credentials_form)) {
203
-            echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
204
-        }
205
-    }
206
-
207
-
208
-    /**
209
-     *    verify_filepath_and_permissions
210
-     *    checks that a file is readable and has sufficient file permissions set to access
211
-     *
212
-     * @access public
213
-     * @param string $full_file_path - full server path to the folder or file
214
-     * @param string $file_name      - name of file if checking a file
215
-     * @param string $file_ext       - file extension (ie: "php") if checking a file
216
-     * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
217
-     * @return bool
218
-     */
219
-    public static function verify_filepath_and_permissions(
220
-        $full_file_path = '',
221
-        $file_name = '',
222
-        $file_ext = '',
223
-        $type_of_file = ''
224
-    ) {
225
-        // load WP_Filesystem and set file permissions
226
-        $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
227
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
228
-        if (! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
-            $file_name = ! empty($type_of_file) ? $file_name . ' ' . $type_of_file : $file_name;
230
-            $file_name .= ! empty($file_ext) ? ' file' : ' folder';
231
-            $msg       = sprintf(
232
-                __(
233
-                    'The requested %1$s could not be found or is not readable, possibly due to an incorrect filepath, or incorrect file permissions.%2$s',
234
-                    'event_espresso'
235
-                ),
236
-                $file_name,
237
-                '<br />'
238
-            );
239
-            if (EEH_File::exists($full_file_path)) {
240
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, $type_of_file);
241
-            } else {
242
-                // no file permissions means the file was not found
243
-                $msg .= sprintf(
244
-                    __('Please ensure the following path is correct: "%s".', 'event_espresso'),
245
-                    $full_file_path
246
-                );
247
-            }
248
-            if (defined('WP_DEBUG') && WP_DEBUG) {
249
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
250
-            }
251
-            return false;
252
-        }
253
-        return true;
254
-    }
255
-
256
-
257
-    /**
258
-     * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a
259
-     * file or folder
260
-     *
261
-     * @access private
262
-     * @param string $full_file_path - full server path to the folder or file
263
-     * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
264
-     * @return string
265
-     */
266
-    private static function _permissions_error_for_unreadable_filepath($full_file_path = '', $type_of_file = '')
267
-    {
268
-        // load WP_Filesystem and set file permissions
269
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
270
-        // check file permissions
271
-        $perms = $wp_filesystem->getchmod(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
272
-        if ($perms) {
273
-            // file permissions exist, but way be set incorrectly
274
-            $type_of_file = ! empty($type_of_file) ? $type_of_file . ' ' : '';
275
-            $type_of_file .= ! empty($type_of_file) ? 'file' : 'folder';
276
-            return ' ' . sprintf(
277
-                __(
278
-                    'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.',
279
-                    'event_espresso'
280
-                ),
281
-                $type_of_file,
282
-                $perms
283
-            );
284
-        } else {
285
-            // file exists but file permissions could not be read ?!?!
286
-            return ' ' . sprintf(
287
-                __(
288
-                    'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".',
289
-                    'event_espresso'
290
-                ),
291
-                $full_file_path
292
-            );
293
-        }
294
-    }
295
-
296
-
297
-    /**
298
-     * ensure_folder_exists_and_is_writable
299
-     * ensures that a folder exists and is writable, will attempt to create folder if it does not exist
300
-     * Also ensures all the parent folders exist, and if not tries to create them.
301
-     * Also, if this function creates the folder, adds a .htaccess file and index.html file
302
-     *
303
-     * @param string $folder
304
-     * @return bool false if folder isn't writable; true if it exists and is writeable,
305
-     */
306
-    public static function ensure_folder_exists_and_is_writable($folder = '')
307
-    {
308
-        if (empty($folder)) {
309
-            return false;
310
-        }
311
-        // remove ending /
312
-        $folder        = EEH_File::standardise_directory_separators(rtrim($folder, '/\\'));
313
-        $parent_folder = EEH_File::get_parent_folder($folder);
314
-        // add / to folder
315
-        $folder        = EEH_File::end_with_directory_separator($folder);
316
-        $wp_filesystem = EEH_File::_get_wp_filesystem($folder);
317
-        $remote_dir    = EEH_File::convert_local_filepath_to_remote_filepath($folder);
318
-        if (! $wp_filesystem->is_dir($remote_dir)) {
319
-            // ok so it doesn't exist. Does its parent? Can we write to it?
320
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
321
-                return false;
322
-            }
323
-            if (! EEH_File::verify_is_writable($parent_folder, 'folder')) {
324
-                return false;
325
-            }
326
-            if (! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
327
-                if (defined('WP_DEBUG') && WP_DEBUG) {
328
-                    $msg = sprintf(__('"%s" could not be created.', 'event_espresso'), $folder);
329
-                    $msg .= EEH_File::_permissions_error_for_unreadable_filepath($folder);
330
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
331
-                }
332
-                return false;
333
-            }
334
-            EEH_File::add_index_file($folder);
335
-        } elseif (! EEH_File::verify_is_writable($folder, 'folder')) {
336
-            return false;
337
-        }
338
-        return true;
339
-    }
340
-
341
-
342
-    /**
343
-     * verify_is_writable - checks if a file or folder is writable
344
-     *
345
-     * @param string $full_path      - full server path to file or folder
346
-     * @param string $file_or_folder - whether checking a file or folder
347
-     * @return bool
348
-     */
349
-    public static function verify_is_writable($full_path = '', $file_or_folder = 'folder')
350
-    {
351
-        // load WP_Filesystem and set file permissions
352
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_path);
353
-        $full_path     = EEH_File::standardise_directory_separators($full_path);
354
-        $remote_path   = EEH_File::convert_local_filepath_to_remote_filepath($full_path);
355
-        $remote_path   = rtrim($remote_path, '/\\');
356
-        if (! $wp_filesystem->is_writable($remote_path)) {
357
-            if (defined('WP_DEBUG') && WP_DEBUG) {
358
-                $msg = sprintf(__('The "%1$s" %2$s is not writable.', 'event_espresso'), $full_path, $file_or_folder);
359
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_path);
360
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
361
-            }
362
-            return false;
363
-        }
364
-        return true;
365
-    }
366
-
367
-
368
-    /**
369
-     * ensure_file_exists_and_is_writable
370
-     * ensures that a file exists and is writable, will attempt to create file if it does not exist.
371
-     * Also ensures all the parent folders exist, and if not tries to create them.
372
-     *
373
-     * @param string $full_file_path
374
-     * @return bool
375
-     */
376
-    public static function ensure_file_exists_and_is_writable($full_file_path = '')
377
-    {
378
-        // load WP_Filesystem and set file permissions
379
-        $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
380
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
381
-        $parent_folder  = EEH_File::get_parent_folder($full_file_path);
382
-        if (! EEH_File::exists($full_file_path)) {
383
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
384
-                return false;
385
-            }
386
-            if (! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
387
-                if (defined('WP_DEBUG') && WP_DEBUG) {
388
-                    $msg = sprintf(__('The "%s" file could not be created.', 'event_espresso'), $full_file_path);
389
-                    $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
390
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
391
-                }
392
-                return false;
393
-            }
394
-        }
395
-        if (! EEH_File::verify_is_writable($full_file_path, 'file')) {
396
-            return false;
397
-        }
398
-        return true;
399
-    }
400
-
401
-
402
-    /**
403
-     * Gets the parent folder. If provided with file, gets the folder that contains it.
404
-     * If provided a folder, gets its parent folder.
405
-     *
406
-     * @param string $file_or_folder_path
407
-     * @return string parent folder, ENDING with a directory separator
408
-     */
409
-    public static function get_parent_folder($file_or_folder_path)
410
-    {
411
-        // find the last /, ignoring a / on the very end
412
-        // eg if given "/var/something/somewhere/", we want to get "somewhere"'s
413
-        // parent folder, "/var/something/"
414
-        $ds = strlen($file_or_folder_path) > 1
415
-            ? strrpos($file_or_folder_path, '/', -2)
416
-            : strlen($file_or_folder_path);
417
-        return substr($file_or_folder_path, 0, $ds + 1);
418
-    }
419
-
420
-
421
-    /**
422
-     * get_file_contents
423
-     *
424
-     * @param string $full_file_path
425
-     * @return string
426
-     */
427
-    public static function get_file_contents($full_file_path = '')
428
-    {
429
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
430
-        if (EEH_File::verify_filepath_and_permissions(
431
-            $full_file_path,
432
-            EEH_File::get_filename_from_filepath($full_file_path),
433
-            EEH_File::get_file_extension($full_file_path)
434
-        )) {
435
-            // load WP_Filesystem and set file permissions
436
-            $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
437
-            return $wp_filesystem->get_contents(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
438
-        }
439
-        return '';
440
-    }
441
-
442
-
443
-    /**
444
-     * write_file
445
-     *
446
-     * @param string $full_file_path
447
-     * @param string $file_contents - the content to be written to the file
448
-     * @param string $file_type
449
-     * @return bool
450
-     */
451
-    public static function write_to_file($full_file_path = '', $file_contents = '', $file_type = '')
452
-    {
453
-        $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
454
-        $file_type      = ! empty($file_type) ? rtrim($file_type, ' ') . ' ' : '';
455
-        $folder         = EEH_File::remove_filename_from_filepath($full_file_path);
456
-        if (! EEH_File::verify_is_writable($folder, 'folder')) {
457
-            if (defined('WP_DEBUG') && WP_DEBUG) {
458
-                $msg =
459
-                    sprintf(
460
-                        __('The %1$sfile located at "%2$s" is not writable.', 'event_espresso'),
461
-                        $file_type,
462
-                        $full_file_path
463
-                    );
464
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
465
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
466
-            }
467
-            return false;
468
-        }
469
-        // load WP_Filesystem and set file permissions
470
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
471
-        // write the file
472
-        if (! $wp_filesystem->put_contents(
473
-            EEH_File::convert_local_filepath_to_remote_filepath($full_file_path),
474
-            $file_contents
475
-        )) {
476
-            if (defined('WP_DEBUG') && WP_DEBUG) {
477
-                $msg =
478
-                    sprintf(
479
-                        __('The %1$sfile located at "%2$s" could not be written to.', 'event_espresso'),
480
-                        $file_type,
481
-                        $full_file_path
482
-                    );
483
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, 'f');
484
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
-            }
486
-            return false;
487
-        }
488
-        return true;
489
-    }
490
-
491
-
492
-    /**
493
-     * Wrapper for WP_Filesystem_Base::delete
494
-     *
495
-     * @param string         $filepath
496
-     * @param boolean        $recursive
497
-     * @param boolean|string $type 'd' for directory, 'f' for file
498
-     * @return boolean
499
-     */
500
-    public static function delete($filepath, $recursive = false, $type = false)
501
-    {
502
-        $wp_filesystem = EEH_File::_get_wp_filesystem();
503
-        return $wp_filesystem->delete($filepath, $recursive, $type);
504
-    }
505
-
506
-
507
-    /**
508
-     * exists
509
-     * checks if a file exists using the WP filesystem
510
-     *
511
-     * @param string $full_file_path
512
-     * @return bool
513
-     */
514
-    public static function exists($full_file_path = '')
515
-    {
516
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
517
-        return $wp_filesystem->exists(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
518
-    }
519
-
520
-
521
-    /**
522
-     * is_readable
523
-     * checks if a file is_readable using the WP filesystem
524
-     *
525
-     * @param string $full_file_path
526
-     * @return bool
527
-     */
528
-    public static function is_readable($full_file_path = '')
529
-    {
530
-        $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
531
-        return $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
532
-    }
533
-
534
-
535
-    /**
536
-     * remove_filename_from_filepath
537
-     * given a full path to a file including the filename itself, this removes  the filename and returns the path, up
538
-     * to, but NOT including the filename OR slash
539
-     *
540
-     * @param string $full_file_path
541
-     * @return string
542
-     */
543
-    public static function remove_filename_from_filepath($full_file_path = '')
544
-    {
545
-        return pathinfo($full_file_path, PATHINFO_DIRNAME);
546
-    }
547
-
548
-
549
-    /**
550
-     * get_filename_from_filepath. Arguably the same as basename()
551
-     *
552
-     * @param string $full_file_path
553
-     * @return string
554
-     */
555
-    public static function get_filename_from_filepath($full_file_path = '')
556
-    {
557
-        return pathinfo($full_file_path, PATHINFO_BASENAME);
558
-    }
559
-
560
-
561
-    /**
562
-     * get_file_extension
563
-     *
564
-     * @param string $full_file_path
565
-     * @return string
566
-     */
567
-    public static function get_file_extension($full_file_path = '')
568
-    {
569
-        return pathinfo($full_file_path, PATHINFO_EXTENSION);
570
-    }
571
-
572
-
573
-    /**
574
-     * add_htaccess_deny_from_all so the web server cannot access this folder
575
-     *
576
-     * @param string $folder
577
-     * @return bool
578
-     */
579
-    public static function add_htaccess_deny_from_all($folder = '')
580
-    {
581
-        $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
582
-        if (! EEH_File::exists($folder . '.htaccess')) {
583
-            if (! EEH_File::write_to_file($folder . '.htaccess', 'deny from all', '.htaccess')) {
584
-                return false;
585
-            }
586
-        }
587
-
588
-        return true;
589
-    }
590
-
591
-
592
-    /**
593
-     * Adds an index file to this folder, so folks can't list all the file's contents
594
-     *
595
-     * @param string $folder
596
-     * @return boolean
597
-     */
598
-    public static function add_index_file($folder)
599
-    {
600
-        $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
601
-        if (! EEH_File::exists($folder . 'index.php')) {
602
-            if (! EEH_File::write_to_file(
603
-                $folder . 'index.php',
604
-                'You are not permitted to read from this folder',
605
-                '.php'
606
-            )) {
607
-                return false;
608
-            }
609
-        }
610
-        return true;
611
-    }
612
-
613
-
614
-    /**
615
-     * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php),
616
-     * extract that classname.
617
-     *
618
-     * @param string $file_path
619
-     * @return string
620
-     */
621
-    public static function get_classname_from_filepath_with_standard_filename($file_path)
622
-    {
623
-        // extract file from path
624
-        $filename = basename($file_path);
625
-        // now remove the first period and everything after
626
-        $pos_of_first_period = strpos($filename, '.');
627
-        return substr($filename, 0, $pos_of_first_period);
628
-    }
629
-
630
-
631
-    /**
632
-     * standardise_directory_separators
633
-     *  convert all directory separators in a file path.
634
-     *
635
-     * @param string $file_path
636
-     * @param bool   $rtrim will remove trailing backslash
637
-     * @return string
638
-     */
639
-    public static function standardise_directory_separators($file_path, $rtrim = false)
640
-    {
641
-        $file_path = $rtrim ? rtrim($file_path, '/\\') : $file_path;
642
-        return str_replace(['\\', '/'], '/', $file_path);
643
-    }
644
-
645
-
646
-    /**
647
-     * end_with_directory_separator
648
-     *  ensures that file path ends with '/'
649
-     *
650
-     * @param string $file_path
651
-     * @return string
652
-     */
653
-    public static function end_with_directory_separator($file_path)
654
-    {
655
-        return rtrim($file_path, '/\\') . '/';
656
-    }
657
-
658
-
659
-    /**
660
-     * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators
661
-     *
662
-     * @param $file_path
663
-     * @return string
664
-     */
665
-    public static function standardise_and_end_with_directory_separator($file_path)
666
-    {
667
-        return self::end_with_directory_separator(self::standardise_directory_separators($file_path));
668
-    }
669
-
670
-
671
-    /**
672
-     * takes the folder name (with or without trailing slash) and finds the files it in,
673
-     * and what the class's name inside of each should be.
674
-     *
675
-     * @param array   $folder_paths
676
-     * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically;
677
-     *                                   if FALSE (Default), returned array will be indexed by the filenames minus
678
-     *                                   extensions. Set it TRUE if you know there are files in the directory with the
679
-     *                                   same name but different extensions
680
-     * @return array if $index_numerically == TRUE keys are numeric ,
681
-     *                                   if $index_numerically == FALSE (Default) keys are what the class names SHOULD
682
-     *                                   be; and values are their file paths
683
-     */
684
-    public static function get_contents_of_folders($folder_paths = [], $index_numerically = false)
685
-    {
686
-        $class_to_folder_path = [];
687
-        foreach ($folder_paths as $folder_path) {
688
-            $folder_path = self::standardise_and_end_with_directory_separator($folder_path);
689
-            // load WP_Filesystem and set file permissions
690
-            $files_in_folder      = glob($folder_path . '*');
691
-            $class_to_folder_path = [];
692
-            if ($files_in_folder) {
693
-                foreach ($files_in_folder as $file_path) {
694
-                    // only add files, not folders
695
-                    if (! is_dir($file_path)) {
696
-                        if ($index_numerically) {
697
-                            $class_to_folder_path[] = $file_path;
698
-                        } else {
699
-                            $classname =
700
-                                self::get_classname_from_filepath_with_standard_filename($file_path);
701
-                            $class_to_folder_path[ $classname ] = $file_path;
702
-                        }
703
-                    }
704
-                }
705
-            }
706
-        }
707
-        return $class_to_folder_path;
708
-    }
709
-
710
-
711
-    /**
712
-     * Copies a file. Mostly a wrapper of WP_Filesystem::copy
713
-     *
714
-     * @param string  $source_file
715
-     * @param string  $destination_file
716
-     * @param boolean $overwrite
717
-     * @return boolean success
718
-     */
719
-    public static function copy($source_file, $destination_file, $overwrite = false)
720
-    {
721
-        $source_file      = EEH_File::validateFileForCopyOrMove($source_file);
722
-        $destination_file = EEH_File::validateFolderForCopyOrMove($destination_file);
723
-        if (! $source_file || ! $destination_file) {
724
-            return false;
725
-        }
726
-        // load WP_Filesystem and set file permissions
727
-        $wp_filesystem = EEH_File::_get_wp_filesystem($destination_file);
728
-        // write the file
729
-        $copied = $wp_filesystem->copy(
730
-            EEH_File::convert_local_filepath_to_remote_filepath($source_file),
731
-            EEH_File::convert_local_filepath_to_remote_filepath($destination_file),
732
-            $overwrite
733
-        );
734
-        if (! $copied) {
735
-            if (defined('WP_DEBUG') && WP_DEBUG) {
736
-                $msg = sprintf(
737
-                    __(
738
-                        'Attempted writing to file %1$s, but could not, probably because of permissions issues',
739
-                        'event_espresso'
740
-                    ),
741
-                    $source_file
742
-                );
743
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($source_file, 'f');
744
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
745
-            }
746
-            return false;
747
-        }
748
-        return true;
749
-    }
750
-
751
-
752
-    /**
753
-     * Reports whether or not the filepath is in the EE uploads folder or not
754
-     *
755
-     * @param string $filepath
756
-     * @return boolean
757
-     */
758
-    public static function is_in_uploads_folder($filepath)
759
-    {
760
-        $uploads = wp_upload_dir();
761
-        return strpos($filepath, $uploads['basedir']) === 0;
762
-    }
763
-
764
-
765
-    /**
766
-     * Given a "local" filepath (what you probably thought was the only filepath),
767
-     * converts it into a "remote" filepath (the filepath the currently-in-use
768
-     * $wp_filesystem needs to use access the folder or file).
769
-     * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins
770
-     *
771
-     * @param string $local_filepath the filepath to the folder/file locally
772
-     * @return string the remote filepath (eg the filepath the filesystem method, eg
773
-     *                               ftp or ssh, will use to access the folder
774
-     */
775
-    public static function convert_local_filepath_to_remote_filepath($local_filepath)
776
-    {
777
-        $wp_filesystem = EEH_File::_get_wp_filesystem($local_filepath);
778
-        return str_replace(WP_CONTENT_DIR . '/', $wp_filesystem->wp_content_dir(), $local_filepath);
779
-    }
780
-
781
-
782
-    /**
783
-     * wrapper for WP_Filesystem::chmod()
784
-     *
785
-     * @param string    $file      Path to the file.
786
-     * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
787
-     *                             0755 for directories. Default false.
788
-     * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
789
-     *                             Default false.
790
-     * @return bool True on success, false on failure.
791
-     */
792
-    public static function chmod($file, $mode = false, $recursive = false)
793
-    {
794
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
795
-        return $wp_filesystem->chmod($file, $mode, $recursive);
796
-    }
797
-
798
-
799
-    /**
800
-     * wrapper for WP_Filesystem::getchmod()
801
-     *
802
-     * @param string $file Path to the file.
803
-     * @return string Mode of the file (the last 3 digits).
804
-     */
805
-    public static function permissions($file)
806
-    {
807
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
808
-        return $wp_filesystem->getchmod($file);
809
-    }
810
-
811
-
812
-    /**
813
-     * wrapper for WP_Filesystem::owner()
814
-     *
815
-     * @param string $file Path to the file.
816
-     * @return string|false Username of the owner on success, false on failure.
817
-     */
818
-    public static function owner($file)
819
-    {
820
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
821
-        return $wp_filesystem->owner($file);
822
-    }
823
-
824
-
825
-    /**
826
-     * wrapper for WP_Filesystem::group()
827
-     *
828
-     * @param string $file Path to the file.
829
-     * @return string|false The group on success, false on failure.
830
-     */
831
-    public static function group($file)
832
-    {
833
-        $wp_filesystem = EEH_File::_get_wp_filesystem($file);
834
-        return $wp_filesystem->group($file);
835
-    }
836
-
837
-
838
-    /**
839
-     * wrapper for WP_Filesystem::move()
840
-     *
841
-     * @param string $source      Path to the source file.
842
-     * @param string $destination Path to the destination file.
843
-     * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
844
-     *                            Default false.
845
-     * @return bool True on success, false on failure.
846
-     */
847
-    public static function move($source, $destination, $overwrite = false)
848
-    {
849
-        // throw new RuntimeException("source: {$source} && destination: {$destination}");
850
-        $source      = EEH_File::validateFileForCopyOrMove($source);
851
-        $destination = EEH_File::validateFolderForCopyOrMove($destination);
852
-        if (! $source || ! $destination) {
853
-            return false;
854
-        }
855
-        $wp_filesystem = EEH_File::_get_wp_filesystem($source);
856
-        if ($wp_filesystem->move($source, $destination, $overwrite)) {
857
-            return true;
858
-        }
859
-        if (defined('WP_DEBUG') && WP_DEBUG) {
860
-            $file        = EEH_File::convert_local_filepath_to_remote_filepath($source);
861
-            $owner       = EEH_File::owner($file);
862
-            $group       = EEH_File::group($file);
863
-            $permissions = EEH_File::permissions($file);
864
-            EE_Error::add_error(
865
-                sprintf(
866
-                    esc_html__(
867
-                        'Unable to move the file "%1$s" to new location (possible permissions errors). The existing "owner:group permissions" for the file are: "%2$s"',
868
-                        'event_espresso'
869
-                    ),
870
-                    $destination,
871
-                    "{$owner}:{$group} $permissions"
872
-                ),
873
-                __FILE__,
874
-                __FUNCTION__,
875
-                __LINE__
876
-            );
877
-        }
878
-        return false;
879
-    }
880
-
881
-
882
-    /**
883
-     * @param string $source_file
884
-     * @return string
885
-     */
886
-    private static function validateFileForCopyOrMove($source_file)
887
-    {
888
-        $full_source_path = EEH_File::standardise_directory_separators($source_file);
889
-        if (! EEH_File::exists($full_source_path)) {
890
-            if (defined('WP_DEBUG') && WP_DEBUG) {
891
-                $msg =
892
-                    sprintf(
893
-                        __('The file located at "%2$s" is not readable or doesn\'t exist.', 'event_espresso'),
894
-                        '',
895
-                        $full_source_path
896
-                    );
897
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_source_path);
898
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
899
-            }
900
-            return '';
901
-        }
902
-        return $full_source_path;
903
-    }
904
-
905
-
906
-    /**
907
-     * @param string $destination_file
908
-     * @return string
909
-     */
910
-    private static function validateFolderForCopyOrMove($destination_file)
911
-    {
912
-        $full_dest_path = EEH_File::standardise_directory_separators($destination_file);
913
-        $folder         = EEH_File::remove_filename_from_filepath($full_dest_path);
914
-        EEH_File::ensure_folder_exists_and_is_writable($folder);
915
-        if (! EEH_File::verify_is_writable($folder, 'folder')) {
916
-            if (defined('WP_DEBUG') && WP_DEBUG) {
917
-                $msg = sprintf(
918
-                    __('The file located at "%2$s" is not writable.', 'event_espresso'),
919
-                    '',
920
-                    $full_dest_path
921
-                );
922
-                $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_dest_path);
923
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
924
-            }
925
-            return '';
926
-        }
927
-        return $full_dest_path;
928
-    }
28
+	/**
29
+	 * @var string $_credentials_form
30
+	 */
31
+	private static $_credentials_form;
32
+
33
+	/**
34
+	 * @var WP_Filesystem_Base $_wp_filesystem
35
+	 */
36
+	protected static $_wp_filesystem;
37
+
38
+
39
+	/**
40
+	 * @param string|null $filepath the filepath we want to work in. If its in the
41
+	 *                              wp uploads directory, we'll want to just use the filesystem directly.
42
+	 *                              If not provided, we have to assume its not in the uploads directory
43
+	 * @return WP_Filesystem_Base
44
+	 */
45
+	private static function _get_wp_filesystem($filepath = null)
46
+	{
47
+		if (apply_filters(
48
+			'FHEE__EEH_File___get_wp_filesystem__allow_using_filesystem_direct',
49
+			$filepath && EEH_File::is_in_uploads_folder($filepath),
50
+			$filepath
51
+		)) {
52
+			return EEH_File::loadAlternateWpFileSystem();
53
+		}
54
+		return EEH_File::loadWpFileSystem();
55
+	}
56
+
57
+
58
+	/**
59
+	 * @return WP_Filesystem_Base
60
+	 */
61
+	private static function loadAlternateWpFileSystem()
62
+	{
63
+		if (! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
64
+			require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
65
+			$method             = 'direct';
66
+			$wp_filesystem_file =
67
+				apply_filters(
68
+					'filesystem_method_file',
69
+					ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php',
70
+					$method
71
+				);
72
+			// added the following validation logic
73
+			// because we allow the filesystem filepath to be filtered,
74
+			// and are loading whatever file the path pointed to,
75
+			// but we were not validating things in any way :scream_emoji:
76
+			$valid_wp_filesystem_types = [
77
+				'direct'     => 'WP_Filesystem_Direct',
78
+				'ftpext'     => 'WP_Filesystem_FTPext',
79
+				'ftpsockets' => 'WP_Filesystem_ftpsockets',
80
+				'ssh2'       => 'WP_Filesystem_SSH2',
81
+			];
82
+			$valid                     = false;
83
+			$wp_filesystem_class       = '';
84
+			foreach ($valid_wp_filesystem_types as $method => $filesystem_class) {
85
+				// if file path matches for one of valid types, then toggle $valid to true
86
+				if (strpos($wp_filesystem_file, $method) > 0) {
87
+					$valid               = true;
88
+					$wp_filesystem_class = $filesystem_class;
89
+				}
90
+			}
91
+			if (! $valid || ! file_exists($wp_filesystem_file)) {
92
+				EE_Error::add_error(
93
+					sprintf(
94
+						__(
95
+							'The supplied WP Filesystem filepath "%1$s" is either missing or invalid.',
96
+							'event_espresso'
97
+						),
98
+						$wp_filesystem_file
99
+					),
100
+					__FILE__,
101
+					__FUNCTION__,
102
+					__LINE__
103
+				);
104
+			}
105
+			// check constants defined, just like in the wp-admin/includes/file.php WP_Filesystem()
106
+			if (! defined('FS_CHMOD_DIR')) {
107
+				define('FS_CHMOD_DIR', (fileperms(ABSPATH) & 0775 | 0755));
108
+			}
109
+			if (! defined('FS_CHMOD_FILE')) {
110
+				define('FS_CHMOD_FILE', (fileperms(ABSPATH . 'index.php') & 0775 | 0644));
111
+			}
112
+			require_once($wp_filesystem_file);
113
+			EEH_File::$_wp_filesystem = new $wp_filesystem_class([]);
114
+		}
115
+		return EEH_File::$_wp_filesystem;
116
+	}
117
+
118
+
119
+	/**
120
+	 * @return WP_Filesystem_Base
121
+	 */
122
+	private static function loadWpFileSystem()
123
+	{
124
+		global $wp_filesystem;
125
+		// no filesystem setup ???
126
+		if (! $wp_filesystem instanceof WP_Filesystem_Base) {
127
+			// if some eager beaver's just trying to get in there too early...
128
+			// let them do it, because we are one of those eager beavers! :P
129
+			/**
130
+			 * more explanations are probably merited. http://codex.wordpress.org/Filesystem_API#Initializing_WP_Filesystem_Base
131
+			 * says WP_Filesystem should be used after 'wp_loaded', but currently EE's activation process
132
+			 * is setup to mostly happen on 'init', and refactoring to have it happen on
133
+			 * 'wp_loaded' is too much work on a BETA milestone.
134
+			 * So this fix is expected to work if the WP files are owned by the server user,
135
+			 * but probably not if the user needs to enter their FTP credentials to modify files
136
+			 * and there may be troubles if the WP files are owned by a different user
137
+			 * than the server user. But both of these issues should exist in 4.4 and earlier too
138
+			 */
139
+			if (false && ! did_action('wp_loaded')) {
140
+				$msg =
141
+					__(
142
+						'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
143
+						'event_espresso'
144
+					);
145
+				if (WP_DEBUG) {
146
+					$msg .= '<br />' . __(
147
+						'The WP Filesystem can not be accessed until after the "wp_loaded" hook has run, so it\'s best not to attempt access until the "admin_init" hookpoint.',
148
+						'event_espresso'
149
+					);
150
+				}
151
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
152
+			}
153
+			// should be loaded if we are past the wp_loaded hook...
154
+			if (! function_exists('WP_Filesystem')) {
155
+				require_once(ABSPATH . 'wp-admin/includes/file.php');
156
+				require_once(ABSPATH . 'wp-admin/includes/template.php');
157
+			}
158
+			// turn on output buffering so that we can capture the credentials form
159
+			ob_start();
160
+			$credentials = request_filesystem_credentials(false);
161
+			// store credentials form for the time being
162
+			EEH_File::$_credentials_form = ob_get_clean();
163
+			// if credentials do NOT exist
164
+			if ($credentials === false) {
165
+				add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
166
+				EE_Error::add_error(
167
+					__(
168
+						'An attempt to access and/or write to a file on the server could not be completed due to a lack of sufficient credentials.',
169
+						'event_espresso'
170
+					),
171
+					__FILE__,
172
+					__FUNCTION__,
173
+					__LINE__
174
+				);
175
+			}
176
+			// basically check for direct or previously configured access
177
+			if (! WP_Filesystem($credentials)
178
+				&& is_wp_error($wp_filesystem->errors)
179
+				&& $wp_filesystem->errors->get_error_code()
180
+			) {
181
+				add_action('admin_notices', ['EEH_File', 'display_request_filesystem_credentials_form'], 999);
182
+				EE_Error::add_error(
183
+					sprintf(
184
+						__('WP Filesystem Error: $1%s', 'event_espresso'),
185
+						$wp_filesystem->errors->get_error_message()
186
+					),
187
+					__FILE__,
188
+					__FUNCTION__,
189
+					__LINE__
190
+				);
191
+			}
192
+		}
193
+		return $wp_filesystem;
194
+	}
195
+
196
+
197
+	/**
198
+	 * display_request_filesystem_credentials_form
199
+	 */
200
+	public static function display_request_filesystem_credentials_form()
201
+	{
202
+		if (! empty(EEH_File::$_credentials_form)) {
203
+			echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
204
+		}
205
+	}
206
+
207
+
208
+	/**
209
+	 *    verify_filepath_and_permissions
210
+	 *    checks that a file is readable and has sufficient file permissions set to access
211
+	 *
212
+	 * @access public
213
+	 * @param string $full_file_path - full server path to the folder or file
214
+	 * @param string $file_name      - name of file if checking a file
215
+	 * @param string $file_ext       - file extension (ie: "php") if checking a file
216
+	 * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
217
+	 * @return bool
218
+	 */
219
+	public static function verify_filepath_and_permissions(
220
+		$full_file_path = '',
221
+		$file_name = '',
222
+		$file_ext = '',
223
+		$type_of_file = ''
224
+	) {
225
+		// load WP_Filesystem and set file permissions
226
+		$wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
227
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
228
+		if (! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
+			$file_name = ! empty($type_of_file) ? $file_name . ' ' . $type_of_file : $file_name;
230
+			$file_name .= ! empty($file_ext) ? ' file' : ' folder';
231
+			$msg       = sprintf(
232
+				__(
233
+					'The requested %1$s could not be found or is not readable, possibly due to an incorrect filepath, or incorrect file permissions.%2$s',
234
+					'event_espresso'
235
+				),
236
+				$file_name,
237
+				'<br />'
238
+			);
239
+			if (EEH_File::exists($full_file_path)) {
240
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, $type_of_file);
241
+			} else {
242
+				// no file permissions means the file was not found
243
+				$msg .= sprintf(
244
+					__('Please ensure the following path is correct: "%s".', 'event_espresso'),
245
+					$full_file_path
246
+				);
247
+			}
248
+			if (defined('WP_DEBUG') && WP_DEBUG) {
249
+				EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
250
+			}
251
+			return false;
252
+		}
253
+		return true;
254
+	}
255
+
256
+
257
+	/**
258
+	 * _permissions_error_for_unreadable_filepath - attempts to determine why permissions are set incorrectly for a
259
+	 * file or folder
260
+	 *
261
+	 * @access private
262
+	 * @param string $full_file_path - full server path to the folder or file
263
+	 * @param string $type_of_file   - general type of file (ie: "module"), this is only used to improve error messages
264
+	 * @return string
265
+	 */
266
+	private static function _permissions_error_for_unreadable_filepath($full_file_path = '', $type_of_file = '')
267
+	{
268
+		// load WP_Filesystem and set file permissions
269
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
270
+		// check file permissions
271
+		$perms = $wp_filesystem->getchmod(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
272
+		if ($perms) {
273
+			// file permissions exist, but way be set incorrectly
274
+			$type_of_file = ! empty($type_of_file) ? $type_of_file . ' ' : '';
275
+			$type_of_file .= ! empty($type_of_file) ? 'file' : 'folder';
276
+			return ' ' . sprintf(
277
+				__(
278
+					'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.',
279
+					'event_espresso'
280
+				),
281
+				$type_of_file,
282
+				$perms
283
+			);
284
+		} else {
285
+			// file exists but file permissions could not be read ?!?!
286
+			return ' ' . sprintf(
287
+				__(
288
+					'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".',
289
+					'event_espresso'
290
+				),
291
+				$full_file_path
292
+			);
293
+		}
294
+	}
295
+
296
+
297
+	/**
298
+	 * ensure_folder_exists_and_is_writable
299
+	 * ensures that a folder exists and is writable, will attempt to create folder if it does not exist
300
+	 * Also ensures all the parent folders exist, and if not tries to create them.
301
+	 * Also, if this function creates the folder, adds a .htaccess file and index.html file
302
+	 *
303
+	 * @param string $folder
304
+	 * @return bool false if folder isn't writable; true if it exists and is writeable,
305
+	 */
306
+	public static function ensure_folder_exists_and_is_writable($folder = '')
307
+	{
308
+		if (empty($folder)) {
309
+			return false;
310
+		}
311
+		// remove ending /
312
+		$folder        = EEH_File::standardise_directory_separators(rtrim($folder, '/\\'));
313
+		$parent_folder = EEH_File::get_parent_folder($folder);
314
+		// add / to folder
315
+		$folder        = EEH_File::end_with_directory_separator($folder);
316
+		$wp_filesystem = EEH_File::_get_wp_filesystem($folder);
317
+		$remote_dir    = EEH_File::convert_local_filepath_to_remote_filepath($folder);
318
+		if (! $wp_filesystem->is_dir($remote_dir)) {
319
+			// ok so it doesn't exist. Does its parent? Can we write to it?
320
+			if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
321
+				return false;
322
+			}
323
+			if (! EEH_File::verify_is_writable($parent_folder, 'folder')) {
324
+				return false;
325
+			}
326
+			if (! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
327
+				if (defined('WP_DEBUG') && WP_DEBUG) {
328
+					$msg = sprintf(__('"%s" could not be created.', 'event_espresso'), $folder);
329
+					$msg .= EEH_File::_permissions_error_for_unreadable_filepath($folder);
330
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
331
+				}
332
+				return false;
333
+			}
334
+			EEH_File::add_index_file($folder);
335
+		} elseif (! EEH_File::verify_is_writable($folder, 'folder')) {
336
+			return false;
337
+		}
338
+		return true;
339
+	}
340
+
341
+
342
+	/**
343
+	 * verify_is_writable - checks if a file or folder is writable
344
+	 *
345
+	 * @param string $full_path      - full server path to file or folder
346
+	 * @param string $file_or_folder - whether checking a file or folder
347
+	 * @return bool
348
+	 */
349
+	public static function verify_is_writable($full_path = '', $file_or_folder = 'folder')
350
+	{
351
+		// load WP_Filesystem and set file permissions
352
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_path);
353
+		$full_path     = EEH_File::standardise_directory_separators($full_path);
354
+		$remote_path   = EEH_File::convert_local_filepath_to_remote_filepath($full_path);
355
+		$remote_path   = rtrim($remote_path, '/\\');
356
+		if (! $wp_filesystem->is_writable($remote_path)) {
357
+			if (defined('WP_DEBUG') && WP_DEBUG) {
358
+				$msg = sprintf(__('The "%1$s" %2$s is not writable.', 'event_espresso'), $full_path, $file_or_folder);
359
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_path);
360
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
361
+			}
362
+			return false;
363
+		}
364
+		return true;
365
+	}
366
+
367
+
368
+	/**
369
+	 * ensure_file_exists_and_is_writable
370
+	 * ensures that a file exists and is writable, will attempt to create file if it does not exist.
371
+	 * Also ensures all the parent folders exist, and if not tries to create them.
372
+	 *
373
+	 * @param string $full_file_path
374
+	 * @return bool
375
+	 */
376
+	public static function ensure_file_exists_and_is_writable($full_file_path = '')
377
+	{
378
+		// load WP_Filesystem and set file permissions
379
+		$wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
380
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
381
+		$parent_folder  = EEH_File::get_parent_folder($full_file_path);
382
+		if (! EEH_File::exists($full_file_path)) {
383
+			if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
384
+				return false;
385
+			}
386
+			if (! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
387
+				if (defined('WP_DEBUG') && WP_DEBUG) {
388
+					$msg = sprintf(__('The "%s" file could not be created.', 'event_espresso'), $full_file_path);
389
+					$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
390
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
391
+				}
392
+				return false;
393
+			}
394
+		}
395
+		if (! EEH_File::verify_is_writable($full_file_path, 'file')) {
396
+			return false;
397
+		}
398
+		return true;
399
+	}
400
+
401
+
402
+	/**
403
+	 * Gets the parent folder. If provided with file, gets the folder that contains it.
404
+	 * If provided a folder, gets its parent folder.
405
+	 *
406
+	 * @param string $file_or_folder_path
407
+	 * @return string parent folder, ENDING with a directory separator
408
+	 */
409
+	public static function get_parent_folder($file_or_folder_path)
410
+	{
411
+		// find the last /, ignoring a / on the very end
412
+		// eg if given "/var/something/somewhere/", we want to get "somewhere"'s
413
+		// parent folder, "/var/something/"
414
+		$ds = strlen($file_or_folder_path) > 1
415
+			? strrpos($file_or_folder_path, '/', -2)
416
+			: strlen($file_or_folder_path);
417
+		return substr($file_or_folder_path, 0, $ds + 1);
418
+	}
419
+
420
+
421
+	/**
422
+	 * get_file_contents
423
+	 *
424
+	 * @param string $full_file_path
425
+	 * @return string
426
+	 */
427
+	public static function get_file_contents($full_file_path = '')
428
+	{
429
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
430
+		if (EEH_File::verify_filepath_and_permissions(
431
+			$full_file_path,
432
+			EEH_File::get_filename_from_filepath($full_file_path),
433
+			EEH_File::get_file_extension($full_file_path)
434
+		)) {
435
+			// load WP_Filesystem and set file permissions
436
+			$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
437
+			return $wp_filesystem->get_contents(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
438
+		}
439
+		return '';
440
+	}
441
+
442
+
443
+	/**
444
+	 * write_file
445
+	 *
446
+	 * @param string $full_file_path
447
+	 * @param string $file_contents - the content to be written to the file
448
+	 * @param string $file_type
449
+	 * @return bool
450
+	 */
451
+	public static function write_to_file($full_file_path = '', $file_contents = '', $file_type = '')
452
+	{
453
+		$full_file_path = EEH_File::standardise_directory_separators($full_file_path);
454
+		$file_type      = ! empty($file_type) ? rtrim($file_type, ' ') . ' ' : '';
455
+		$folder         = EEH_File::remove_filename_from_filepath($full_file_path);
456
+		if (! EEH_File::verify_is_writable($folder, 'folder')) {
457
+			if (defined('WP_DEBUG') && WP_DEBUG) {
458
+				$msg =
459
+					sprintf(
460
+						__('The %1$sfile located at "%2$s" is not writable.', 'event_espresso'),
461
+						$file_type,
462
+						$full_file_path
463
+					);
464
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
465
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
466
+			}
467
+			return false;
468
+		}
469
+		// load WP_Filesystem and set file permissions
470
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
471
+		// write the file
472
+		if (! $wp_filesystem->put_contents(
473
+			EEH_File::convert_local_filepath_to_remote_filepath($full_file_path),
474
+			$file_contents
475
+		)) {
476
+			if (defined('WP_DEBUG') && WP_DEBUG) {
477
+				$msg =
478
+					sprintf(
479
+						__('The %1$sfile located at "%2$s" could not be written to.', 'event_espresso'),
480
+						$file_type,
481
+						$full_file_path
482
+					);
483
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path, 'f');
484
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
485
+			}
486
+			return false;
487
+		}
488
+		return true;
489
+	}
490
+
491
+
492
+	/**
493
+	 * Wrapper for WP_Filesystem_Base::delete
494
+	 *
495
+	 * @param string         $filepath
496
+	 * @param boolean        $recursive
497
+	 * @param boolean|string $type 'd' for directory, 'f' for file
498
+	 * @return boolean
499
+	 */
500
+	public static function delete($filepath, $recursive = false, $type = false)
501
+	{
502
+		$wp_filesystem = EEH_File::_get_wp_filesystem();
503
+		return $wp_filesystem->delete($filepath, $recursive, $type);
504
+	}
505
+
506
+
507
+	/**
508
+	 * exists
509
+	 * checks if a file exists using the WP filesystem
510
+	 *
511
+	 * @param string $full_file_path
512
+	 * @return bool
513
+	 */
514
+	public static function exists($full_file_path = '')
515
+	{
516
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
517
+		return $wp_filesystem->exists(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
518
+	}
519
+
520
+
521
+	/**
522
+	 * is_readable
523
+	 * checks if a file is_readable using the WP filesystem
524
+	 *
525
+	 * @param string $full_file_path
526
+	 * @return bool
527
+	 */
528
+	public static function is_readable($full_file_path = '')
529
+	{
530
+		$wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
531
+		return $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
532
+	}
533
+
534
+
535
+	/**
536
+	 * remove_filename_from_filepath
537
+	 * given a full path to a file including the filename itself, this removes  the filename and returns the path, up
538
+	 * to, but NOT including the filename OR slash
539
+	 *
540
+	 * @param string $full_file_path
541
+	 * @return string
542
+	 */
543
+	public static function remove_filename_from_filepath($full_file_path = '')
544
+	{
545
+		return pathinfo($full_file_path, PATHINFO_DIRNAME);
546
+	}
547
+
548
+
549
+	/**
550
+	 * get_filename_from_filepath. Arguably the same as basename()
551
+	 *
552
+	 * @param string $full_file_path
553
+	 * @return string
554
+	 */
555
+	public static function get_filename_from_filepath($full_file_path = '')
556
+	{
557
+		return pathinfo($full_file_path, PATHINFO_BASENAME);
558
+	}
559
+
560
+
561
+	/**
562
+	 * get_file_extension
563
+	 *
564
+	 * @param string $full_file_path
565
+	 * @return string
566
+	 */
567
+	public static function get_file_extension($full_file_path = '')
568
+	{
569
+		return pathinfo($full_file_path, PATHINFO_EXTENSION);
570
+	}
571
+
572
+
573
+	/**
574
+	 * add_htaccess_deny_from_all so the web server cannot access this folder
575
+	 *
576
+	 * @param string $folder
577
+	 * @return bool
578
+	 */
579
+	public static function add_htaccess_deny_from_all($folder = '')
580
+	{
581
+		$folder = EEH_File::standardise_and_end_with_directory_separator($folder);
582
+		if (! EEH_File::exists($folder . '.htaccess')) {
583
+			if (! EEH_File::write_to_file($folder . '.htaccess', 'deny from all', '.htaccess')) {
584
+				return false;
585
+			}
586
+		}
587
+
588
+		return true;
589
+	}
590
+
591
+
592
+	/**
593
+	 * Adds an index file to this folder, so folks can't list all the file's contents
594
+	 *
595
+	 * @param string $folder
596
+	 * @return boolean
597
+	 */
598
+	public static function add_index_file($folder)
599
+	{
600
+		$folder = EEH_File::standardise_and_end_with_directory_separator($folder);
601
+		if (! EEH_File::exists($folder . 'index.php')) {
602
+			if (! EEH_File::write_to_file(
603
+				$folder . 'index.php',
604
+				'You are not permitted to read from this folder',
605
+				'.php'
606
+			)) {
607
+				return false;
608
+			}
609
+		}
610
+		return true;
611
+	}
612
+
613
+
614
+	/**
615
+	 * Given that the file in $file_path has the normal name, (ie, CLASSNAME.whatever.php),
616
+	 * extract that classname.
617
+	 *
618
+	 * @param string $file_path
619
+	 * @return string
620
+	 */
621
+	public static function get_classname_from_filepath_with_standard_filename($file_path)
622
+	{
623
+		// extract file from path
624
+		$filename = basename($file_path);
625
+		// now remove the first period and everything after
626
+		$pos_of_first_period = strpos($filename, '.');
627
+		return substr($filename, 0, $pos_of_first_period);
628
+	}
629
+
630
+
631
+	/**
632
+	 * standardise_directory_separators
633
+	 *  convert all directory separators in a file path.
634
+	 *
635
+	 * @param string $file_path
636
+	 * @param bool   $rtrim will remove trailing backslash
637
+	 * @return string
638
+	 */
639
+	public static function standardise_directory_separators($file_path, $rtrim = false)
640
+	{
641
+		$file_path = $rtrim ? rtrim($file_path, '/\\') : $file_path;
642
+		return str_replace(['\\', '/'], '/', $file_path);
643
+	}
644
+
645
+
646
+	/**
647
+	 * end_with_directory_separator
648
+	 *  ensures that file path ends with '/'
649
+	 *
650
+	 * @param string $file_path
651
+	 * @return string
652
+	 */
653
+	public static function end_with_directory_separator($file_path)
654
+	{
655
+		return rtrim($file_path, '/\\') . '/';
656
+	}
657
+
658
+
659
+	/**
660
+	 * shorthand for both EEH_FIle::end_with_directory_separator AND EEH_File::standardise_directory_separators
661
+	 *
662
+	 * @param $file_path
663
+	 * @return string
664
+	 */
665
+	public static function standardise_and_end_with_directory_separator($file_path)
666
+	{
667
+		return self::end_with_directory_separator(self::standardise_directory_separators($file_path));
668
+	}
669
+
670
+
671
+	/**
672
+	 * takes the folder name (with or without trailing slash) and finds the files it in,
673
+	 * and what the class's name inside of each should be.
674
+	 *
675
+	 * @param array   $folder_paths
676
+	 * @param boolean $index_numerically if TRUE, the returned array will be indexed numerically;
677
+	 *                                   if FALSE (Default), returned array will be indexed by the filenames minus
678
+	 *                                   extensions. Set it TRUE if you know there are files in the directory with the
679
+	 *                                   same name but different extensions
680
+	 * @return array if $index_numerically == TRUE keys are numeric ,
681
+	 *                                   if $index_numerically == FALSE (Default) keys are what the class names SHOULD
682
+	 *                                   be; and values are their file paths
683
+	 */
684
+	public static function get_contents_of_folders($folder_paths = [], $index_numerically = false)
685
+	{
686
+		$class_to_folder_path = [];
687
+		foreach ($folder_paths as $folder_path) {
688
+			$folder_path = self::standardise_and_end_with_directory_separator($folder_path);
689
+			// load WP_Filesystem and set file permissions
690
+			$files_in_folder      = glob($folder_path . '*');
691
+			$class_to_folder_path = [];
692
+			if ($files_in_folder) {
693
+				foreach ($files_in_folder as $file_path) {
694
+					// only add files, not folders
695
+					if (! is_dir($file_path)) {
696
+						if ($index_numerically) {
697
+							$class_to_folder_path[] = $file_path;
698
+						} else {
699
+							$classname =
700
+								self::get_classname_from_filepath_with_standard_filename($file_path);
701
+							$class_to_folder_path[ $classname ] = $file_path;
702
+						}
703
+					}
704
+				}
705
+			}
706
+		}
707
+		return $class_to_folder_path;
708
+	}
709
+
710
+
711
+	/**
712
+	 * Copies a file. Mostly a wrapper of WP_Filesystem::copy
713
+	 *
714
+	 * @param string  $source_file
715
+	 * @param string  $destination_file
716
+	 * @param boolean $overwrite
717
+	 * @return boolean success
718
+	 */
719
+	public static function copy($source_file, $destination_file, $overwrite = false)
720
+	{
721
+		$source_file      = EEH_File::validateFileForCopyOrMove($source_file);
722
+		$destination_file = EEH_File::validateFolderForCopyOrMove($destination_file);
723
+		if (! $source_file || ! $destination_file) {
724
+			return false;
725
+		}
726
+		// load WP_Filesystem and set file permissions
727
+		$wp_filesystem = EEH_File::_get_wp_filesystem($destination_file);
728
+		// write the file
729
+		$copied = $wp_filesystem->copy(
730
+			EEH_File::convert_local_filepath_to_remote_filepath($source_file),
731
+			EEH_File::convert_local_filepath_to_remote_filepath($destination_file),
732
+			$overwrite
733
+		);
734
+		if (! $copied) {
735
+			if (defined('WP_DEBUG') && WP_DEBUG) {
736
+				$msg = sprintf(
737
+					__(
738
+						'Attempted writing to file %1$s, but could not, probably because of permissions issues',
739
+						'event_espresso'
740
+					),
741
+					$source_file
742
+				);
743
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($source_file, 'f');
744
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
745
+			}
746
+			return false;
747
+		}
748
+		return true;
749
+	}
750
+
751
+
752
+	/**
753
+	 * Reports whether or not the filepath is in the EE uploads folder or not
754
+	 *
755
+	 * @param string $filepath
756
+	 * @return boolean
757
+	 */
758
+	public static function is_in_uploads_folder($filepath)
759
+	{
760
+		$uploads = wp_upload_dir();
761
+		return strpos($filepath, $uploads['basedir']) === 0;
762
+	}
763
+
764
+
765
+	/**
766
+	 * Given a "local" filepath (what you probably thought was the only filepath),
767
+	 * converts it into a "remote" filepath (the filepath the currently-in-use
768
+	 * $wp_filesystem needs to use access the folder or file).
769
+	 * See http://wordpress.stackexchange.com/questions/124900/using-wp-filesystem-in-plugins
770
+	 *
771
+	 * @param string $local_filepath the filepath to the folder/file locally
772
+	 * @return string the remote filepath (eg the filepath the filesystem method, eg
773
+	 *                               ftp or ssh, will use to access the folder
774
+	 */
775
+	public static function convert_local_filepath_to_remote_filepath($local_filepath)
776
+	{
777
+		$wp_filesystem = EEH_File::_get_wp_filesystem($local_filepath);
778
+		return str_replace(WP_CONTENT_DIR . '/', $wp_filesystem->wp_content_dir(), $local_filepath);
779
+	}
780
+
781
+
782
+	/**
783
+	 * wrapper for WP_Filesystem::chmod()
784
+	 *
785
+	 * @param string    $file      Path to the file.
786
+	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
787
+	 *                             0755 for directories. Default false.
788
+	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
789
+	 *                             Default false.
790
+	 * @return bool True on success, false on failure.
791
+	 */
792
+	public static function chmod($file, $mode = false, $recursive = false)
793
+	{
794
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
795
+		return $wp_filesystem->chmod($file, $mode, $recursive);
796
+	}
797
+
798
+
799
+	/**
800
+	 * wrapper for WP_Filesystem::getchmod()
801
+	 *
802
+	 * @param string $file Path to the file.
803
+	 * @return string Mode of the file (the last 3 digits).
804
+	 */
805
+	public static function permissions($file)
806
+	{
807
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
808
+		return $wp_filesystem->getchmod($file);
809
+	}
810
+
811
+
812
+	/**
813
+	 * wrapper for WP_Filesystem::owner()
814
+	 *
815
+	 * @param string $file Path to the file.
816
+	 * @return string|false Username of the owner on success, false on failure.
817
+	 */
818
+	public static function owner($file)
819
+	{
820
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
821
+		return $wp_filesystem->owner($file);
822
+	}
823
+
824
+
825
+	/**
826
+	 * wrapper for WP_Filesystem::group()
827
+	 *
828
+	 * @param string $file Path to the file.
829
+	 * @return string|false The group on success, false on failure.
830
+	 */
831
+	public static function group($file)
832
+	{
833
+		$wp_filesystem = EEH_File::_get_wp_filesystem($file);
834
+		return $wp_filesystem->group($file);
835
+	}
836
+
837
+
838
+	/**
839
+	 * wrapper for WP_Filesystem::move()
840
+	 *
841
+	 * @param string $source      Path to the source file.
842
+	 * @param string $destination Path to the destination file.
843
+	 * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
844
+	 *                            Default false.
845
+	 * @return bool True on success, false on failure.
846
+	 */
847
+	public static function move($source, $destination, $overwrite = false)
848
+	{
849
+		// throw new RuntimeException("source: {$source} && destination: {$destination}");
850
+		$source      = EEH_File::validateFileForCopyOrMove($source);
851
+		$destination = EEH_File::validateFolderForCopyOrMove($destination);
852
+		if (! $source || ! $destination) {
853
+			return false;
854
+		}
855
+		$wp_filesystem = EEH_File::_get_wp_filesystem($source);
856
+		if ($wp_filesystem->move($source, $destination, $overwrite)) {
857
+			return true;
858
+		}
859
+		if (defined('WP_DEBUG') && WP_DEBUG) {
860
+			$file        = EEH_File::convert_local_filepath_to_remote_filepath($source);
861
+			$owner       = EEH_File::owner($file);
862
+			$group       = EEH_File::group($file);
863
+			$permissions = EEH_File::permissions($file);
864
+			EE_Error::add_error(
865
+				sprintf(
866
+					esc_html__(
867
+						'Unable to move the file "%1$s" to new location (possible permissions errors). The existing "owner:group permissions" for the file are: "%2$s"',
868
+						'event_espresso'
869
+					),
870
+					$destination,
871
+					"{$owner}:{$group} $permissions"
872
+				),
873
+				__FILE__,
874
+				__FUNCTION__,
875
+				__LINE__
876
+			);
877
+		}
878
+		return false;
879
+	}
880
+
881
+
882
+	/**
883
+	 * @param string $source_file
884
+	 * @return string
885
+	 */
886
+	private static function validateFileForCopyOrMove($source_file)
887
+	{
888
+		$full_source_path = EEH_File::standardise_directory_separators($source_file);
889
+		if (! EEH_File::exists($full_source_path)) {
890
+			if (defined('WP_DEBUG') && WP_DEBUG) {
891
+				$msg =
892
+					sprintf(
893
+						__('The file located at "%2$s" is not readable or doesn\'t exist.', 'event_espresso'),
894
+						'',
895
+						$full_source_path
896
+					);
897
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_source_path);
898
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
899
+			}
900
+			return '';
901
+		}
902
+		return $full_source_path;
903
+	}
904
+
905
+
906
+	/**
907
+	 * @param string $destination_file
908
+	 * @return string
909
+	 */
910
+	private static function validateFolderForCopyOrMove($destination_file)
911
+	{
912
+		$full_dest_path = EEH_File::standardise_directory_separators($destination_file);
913
+		$folder         = EEH_File::remove_filename_from_filepath($full_dest_path);
914
+		EEH_File::ensure_folder_exists_and_is_writable($folder);
915
+		if (! EEH_File::verify_is_writable($folder, 'folder')) {
916
+			if (defined('WP_DEBUG') && WP_DEBUG) {
917
+				$msg = sprintf(
918
+					__('The file located at "%2$s" is not writable.', 'event_espresso'),
919
+					'',
920
+					$full_dest_path
921
+				);
922
+				$msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_dest_path);
923
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
924
+			}
925
+			return '';
926
+		}
927
+		return $full_dest_path;
928
+	}
929 929
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -60,13 +60,13 @@  discard block
 block discarded – undo
60 60
      */
61 61
     private static function loadAlternateWpFileSystem()
62 62
     {
63
-        if (! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
64
-            require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
63
+        if ( ! EEH_File::$_wp_filesystem instanceof WP_Filesystem_Base) {
64
+            require_once(ABSPATH.'wp-admin/includes/class-wp-filesystem-base.php');
65 65
             $method             = 'direct';
66 66
             $wp_filesystem_file =
67 67
                 apply_filters(
68 68
                     'filesystem_method_file',
69
-                    ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php',
69
+                    ABSPATH.'wp-admin/includes/class-wp-filesystem-'.$method.'.php',
70 70
                     $method
71 71
                 );
72 72
             // added the following validation logic
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
                     $wp_filesystem_class = $filesystem_class;
89 89
                 }
90 90
             }
91
-            if (! $valid || ! file_exists($wp_filesystem_file)) {
91
+            if ( ! $valid || ! file_exists($wp_filesystem_file)) {
92 92
                 EE_Error::add_error(
93 93
                     sprintf(
94 94
                         __(
@@ -103,11 +103,11 @@  discard block
 block discarded – undo
103 103
                 );
104 104
             }
105 105
             // check constants defined, just like in the wp-admin/includes/file.php WP_Filesystem()
106
-            if (! defined('FS_CHMOD_DIR')) {
106
+            if ( ! defined('FS_CHMOD_DIR')) {
107 107
                 define('FS_CHMOD_DIR', (fileperms(ABSPATH) & 0775 | 0755));
108 108
             }
109
-            if (! defined('FS_CHMOD_FILE')) {
110
-                define('FS_CHMOD_FILE', (fileperms(ABSPATH . 'index.php') & 0775 | 0644));
109
+            if ( ! defined('FS_CHMOD_FILE')) {
110
+                define('FS_CHMOD_FILE', (fileperms(ABSPATH.'index.php') & 0775 | 0644));
111 111
             }
112 112
             require_once($wp_filesystem_file);
113 113
             EEH_File::$_wp_filesystem = new $wp_filesystem_class([]);
@@ -123,7 +123,7 @@  discard block
 block discarded – undo
123 123
     {
124 124
         global $wp_filesystem;
125 125
         // no filesystem setup ???
126
-        if (! $wp_filesystem instanceof WP_Filesystem_Base) {
126
+        if ( ! $wp_filesystem instanceof WP_Filesystem_Base) {
127 127
             // if some eager beaver's just trying to get in there too early...
128 128
             // let them do it, because we are one of those eager beavers! :P
129 129
             /**
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
                         'event_espresso'
144 144
                     );
145 145
                 if (WP_DEBUG) {
146
-                    $msg .= '<br />' . __(
146
+                    $msg .= '<br />'.__(
147 147
                         'The WP Filesystem can not be accessed until after the "wp_loaded" hook has run, so it\'s best not to attempt access until the "admin_init" hookpoint.',
148 148
                         'event_espresso'
149 149
                     );
@@ -151,9 +151,9 @@  discard block
 block discarded – undo
151 151
                 EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
152 152
             }
153 153
             // should be loaded if we are past the wp_loaded hook...
154
-            if (! function_exists('WP_Filesystem')) {
155
-                require_once(ABSPATH . 'wp-admin/includes/file.php');
156
-                require_once(ABSPATH . 'wp-admin/includes/template.php');
154
+            if ( ! function_exists('WP_Filesystem')) {
155
+                require_once(ABSPATH.'wp-admin/includes/file.php');
156
+                require_once(ABSPATH.'wp-admin/includes/template.php');
157 157
             }
158 158
             // turn on output buffering so that we can capture the credentials form
159 159
             ob_start();
@@ -174,7 +174,7 @@  discard block
 block discarded – undo
174 174
                 );
175 175
             }
176 176
             // basically check for direct or previously configured access
177
-            if (! WP_Filesystem($credentials)
177
+            if ( ! WP_Filesystem($credentials)
178 178
                 && is_wp_error($wp_filesystem->errors)
179 179
                 && $wp_filesystem->errors->get_error_code()
180 180
             ) {
@@ -199,8 +199,8 @@  discard block
 block discarded – undo
199 199
      */
200 200
     public static function display_request_filesystem_credentials_form()
201 201
     {
202
-        if (! empty(EEH_File::$_credentials_form)) {
203
-            echo '<div class="updated espresso-notices-attention"><p>' . EEH_File::$_credentials_form . '</p></div>';
202
+        if ( ! empty(EEH_File::$_credentials_form)) {
203
+            echo '<div class="updated espresso-notices-attention"><p>'.EEH_File::$_credentials_form.'</p></div>';
204 204
         }
205 205
     }
206 206
 
@@ -225,8 +225,8 @@  discard block
 block discarded – undo
225 225
         // load WP_Filesystem and set file permissions
226 226
         $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
227 227
         $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
228
-        if (! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
-            $file_name = ! empty($type_of_file) ? $file_name . ' ' . $type_of_file : $file_name;
228
+        if ( ! $wp_filesystem->is_readable(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
229
+            $file_name = ! empty($type_of_file) ? $file_name.' '.$type_of_file : $file_name;
230 230
             $file_name .= ! empty($file_ext) ? ' file' : ' folder';
231 231
             $msg       = sprintf(
232 232
                 __(
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
                 );
247 247
             }
248 248
             if (defined('WP_DEBUG') && WP_DEBUG) {
249
-                EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
249
+                EE_Error::add_error($msg.'||'.$msg, __FILE__, __FUNCTION__, __LINE__);
250 250
             }
251 251
             return false;
252 252
         }
@@ -271,9 +271,9 @@  discard block
 block discarded – undo
271 271
         $perms = $wp_filesystem->getchmod(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path));
272 272
         if ($perms) {
273 273
             // file permissions exist, but way be set incorrectly
274
-            $type_of_file = ! empty($type_of_file) ? $type_of_file . ' ' : '';
274
+            $type_of_file = ! empty($type_of_file) ? $type_of_file.' ' : '';
275 275
             $type_of_file .= ! empty($type_of_file) ? 'file' : 'folder';
276
-            return ' ' . sprintf(
276
+            return ' '.sprintf(
277 277
                 __(
278 278
                     'File permissions for the requested %1$s are currently set at "%2$s". The recommended permissions are 644 for files and 755 for folders.',
279 279
                     'event_espresso'
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
             );
284 284
         } else {
285 285
             // file exists but file permissions could not be read ?!?!
286
-            return ' ' . sprintf(
286
+            return ' '.sprintf(
287 287
                 __(
288 288
                     'Please ensure that the server and/or PHP configuration allows the current process to access the following file: "%s".',
289 289
                     'event_espresso'
@@ -315,15 +315,15 @@  discard block
 block discarded – undo
315 315
         $folder        = EEH_File::end_with_directory_separator($folder);
316 316
         $wp_filesystem = EEH_File::_get_wp_filesystem($folder);
317 317
         $remote_dir    = EEH_File::convert_local_filepath_to_remote_filepath($folder);
318
-        if (! $wp_filesystem->is_dir($remote_dir)) {
318
+        if ( ! $wp_filesystem->is_dir($remote_dir)) {
319 319
             // ok so it doesn't exist. Does its parent? Can we write to it?
320
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
320
+            if ( ! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
321 321
                 return false;
322 322
             }
323
-            if (! EEH_File::verify_is_writable($parent_folder, 'folder')) {
323
+            if ( ! EEH_File::verify_is_writable($parent_folder, 'folder')) {
324 324
                 return false;
325 325
             }
326
-            if (! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
326
+            if ( ! $wp_filesystem->mkdir(EEH_File::convert_local_filepath_to_remote_filepath($folder))) {
327 327
                 if (defined('WP_DEBUG') && WP_DEBUG) {
328 328
                     $msg = sprintf(__('"%s" could not be created.', 'event_espresso'), $folder);
329 329
                     $msg .= EEH_File::_permissions_error_for_unreadable_filepath($folder);
@@ -332,7 +332,7 @@  discard block
 block discarded – undo
332 332
                 return false;
333 333
             }
334 334
             EEH_File::add_index_file($folder);
335
-        } elseif (! EEH_File::verify_is_writable($folder, 'folder')) {
335
+        } elseif ( ! EEH_File::verify_is_writable($folder, 'folder')) {
336 336
             return false;
337 337
         }
338 338
         return true;
@@ -353,7 +353,7 @@  discard block
 block discarded – undo
353 353
         $full_path     = EEH_File::standardise_directory_separators($full_path);
354 354
         $remote_path   = EEH_File::convert_local_filepath_to_remote_filepath($full_path);
355 355
         $remote_path   = rtrim($remote_path, '/\\');
356
-        if (! $wp_filesystem->is_writable($remote_path)) {
356
+        if ( ! $wp_filesystem->is_writable($remote_path)) {
357 357
             if (defined('WP_DEBUG') && WP_DEBUG) {
358 358
                 $msg = sprintf(__('The "%1$s" %2$s is not writable.', 'event_espresso'), $full_path, $file_or_folder);
359 359
                 $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_path);
@@ -379,11 +379,11 @@  discard block
 block discarded – undo
379 379
         $wp_filesystem  = EEH_File::_get_wp_filesystem($full_file_path);
380 380
         $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
381 381
         $parent_folder  = EEH_File::get_parent_folder($full_file_path);
382
-        if (! EEH_File::exists($full_file_path)) {
383
-            if (! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
382
+        if ( ! EEH_File::exists($full_file_path)) {
383
+            if ( ! EEH_File::ensure_folder_exists_and_is_writable($parent_folder)) {
384 384
                 return false;
385 385
             }
386
-            if (! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
386
+            if ( ! $wp_filesystem->touch(EEH_File::convert_local_filepath_to_remote_filepath($full_file_path))) {
387 387
                 if (defined('WP_DEBUG') && WP_DEBUG) {
388 388
                     $msg = sprintf(__('The "%s" file could not be created.', 'event_espresso'), $full_file_path);
389 389
                     $msg .= EEH_File::_permissions_error_for_unreadable_filepath($full_file_path);
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
                 return false;
393 393
             }
394 394
         }
395
-        if (! EEH_File::verify_is_writable($full_file_path, 'file')) {
395
+        if ( ! EEH_File::verify_is_writable($full_file_path, 'file')) {
396 396
             return false;
397 397
         }
398 398
         return true;
@@ -451,9 +451,9 @@  discard block
 block discarded – undo
451 451
     public static function write_to_file($full_file_path = '', $file_contents = '', $file_type = '')
452 452
     {
453 453
         $full_file_path = EEH_File::standardise_directory_separators($full_file_path);
454
-        $file_type      = ! empty($file_type) ? rtrim($file_type, ' ') . ' ' : '';
454
+        $file_type      = ! empty($file_type) ? rtrim($file_type, ' ').' ' : '';
455 455
         $folder         = EEH_File::remove_filename_from_filepath($full_file_path);
456
-        if (! EEH_File::verify_is_writable($folder, 'folder')) {
456
+        if ( ! EEH_File::verify_is_writable($folder, 'folder')) {
457 457
             if (defined('WP_DEBUG') && WP_DEBUG) {
458 458
                 $msg =
459 459
                     sprintf(
@@ -469,7 +469,7 @@  discard block
 block discarded – undo
469 469
         // load WP_Filesystem and set file permissions
470 470
         $wp_filesystem = EEH_File::_get_wp_filesystem($full_file_path);
471 471
         // write the file
472
-        if (! $wp_filesystem->put_contents(
472
+        if ( ! $wp_filesystem->put_contents(
473 473
             EEH_File::convert_local_filepath_to_remote_filepath($full_file_path),
474 474
             $file_contents
475 475
         )) {
@@ -579,8 +579,8 @@  discard block
 block discarded – undo
579 579
     public static function add_htaccess_deny_from_all($folder = '')
580 580
     {
581 581
         $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
582
-        if (! EEH_File::exists($folder . '.htaccess')) {
583
-            if (! EEH_File::write_to_file($folder . '.htaccess', 'deny from all', '.htaccess')) {
582
+        if ( ! EEH_File::exists($folder.'.htaccess')) {
583
+            if ( ! EEH_File::write_to_file($folder.'.htaccess', 'deny from all', '.htaccess')) {
584 584
                 return false;
585 585
             }
586 586
         }
@@ -598,9 +598,9 @@  discard block
 block discarded – undo
598 598
     public static function add_index_file($folder)
599 599
     {
600 600
         $folder = EEH_File::standardise_and_end_with_directory_separator($folder);
601
-        if (! EEH_File::exists($folder . 'index.php')) {
602
-            if (! EEH_File::write_to_file(
603
-                $folder . 'index.php',
601
+        if ( ! EEH_File::exists($folder.'index.php')) {
602
+            if ( ! EEH_File::write_to_file(
603
+                $folder.'index.php',
604 604
                 'You are not permitted to read from this folder',
605 605
                 '.php'
606 606
             )) {
@@ -652,7 +652,7 @@  discard block
 block discarded – undo
652 652
      */
653 653
     public static function end_with_directory_separator($file_path)
654 654
     {
655
-        return rtrim($file_path, '/\\') . '/';
655
+        return rtrim($file_path, '/\\').'/';
656 656
     }
657 657
 
658 658
 
@@ -687,18 +687,18 @@  discard block
 block discarded – undo
687 687
         foreach ($folder_paths as $folder_path) {
688 688
             $folder_path = self::standardise_and_end_with_directory_separator($folder_path);
689 689
             // load WP_Filesystem and set file permissions
690
-            $files_in_folder      = glob($folder_path . '*');
690
+            $files_in_folder      = glob($folder_path.'*');
691 691
             $class_to_folder_path = [];
692 692
             if ($files_in_folder) {
693 693
                 foreach ($files_in_folder as $file_path) {
694 694
                     // only add files, not folders
695
-                    if (! is_dir($file_path)) {
695
+                    if ( ! is_dir($file_path)) {
696 696
                         if ($index_numerically) {
697 697
                             $class_to_folder_path[] = $file_path;
698 698
                         } else {
699 699
                             $classname =
700 700
                                 self::get_classname_from_filepath_with_standard_filename($file_path);
701
-                            $class_to_folder_path[ $classname ] = $file_path;
701
+                            $class_to_folder_path[$classname] = $file_path;
702 702
                         }
703 703
                     }
704 704
                 }
@@ -720,7 +720,7 @@  discard block
 block discarded – undo
720 720
     {
721 721
         $source_file      = EEH_File::validateFileForCopyOrMove($source_file);
722 722
         $destination_file = EEH_File::validateFolderForCopyOrMove($destination_file);
723
-        if (! $source_file || ! $destination_file) {
723
+        if ( ! $source_file || ! $destination_file) {
724 724
             return false;
725 725
         }
726 726
         // load WP_Filesystem and set file permissions
@@ -731,7 +731,7 @@  discard block
 block discarded – undo
731 731
             EEH_File::convert_local_filepath_to_remote_filepath($destination_file),
732 732
             $overwrite
733 733
         );
734
-        if (! $copied) {
734
+        if ( ! $copied) {
735 735
             if (defined('WP_DEBUG') && WP_DEBUG) {
736 736
                 $msg = sprintf(
737 737
                     __(
@@ -775,7 +775,7 @@  discard block
 block discarded – undo
775 775
     public static function convert_local_filepath_to_remote_filepath($local_filepath)
776 776
     {
777 777
         $wp_filesystem = EEH_File::_get_wp_filesystem($local_filepath);
778
-        return str_replace(WP_CONTENT_DIR . '/', $wp_filesystem->wp_content_dir(), $local_filepath);
778
+        return str_replace(WP_CONTENT_DIR.'/', $wp_filesystem->wp_content_dir(), $local_filepath);
779 779
     }
780 780
 
781 781
 
@@ -849,7 +849,7 @@  discard block
 block discarded – undo
849 849
         // throw new RuntimeException("source: {$source} && destination: {$destination}");
850 850
         $source      = EEH_File::validateFileForCopyOrMove($source);
851 851
         $destination = EEH_File::validateFolderForCopyOrMove($destination);
852
-        if (! $source || ! $destination) {
852
+        if ( ! $source || ! $destination) {
853 853
             return false;
854 854
         }
855 855
         $wp_filesystem = EEH_File::_get_wp_filesystem($source);
@@ -886,7 +886,7 @@  discard block
 block discarded – undo
886 886
     private static function validateFileForCopyOrMove($source_file)
887 887
     {
888 888
         $full_source_path = EEH_File::standardise_directory_separators($source_file);
889
-        if (! EEH_File::exists($full_source_path)) {
889
+        if ( ! EEH_File::exists($full_source_path)) {
890 890
             if (defined('WP_DEBUG') && WP_DEBUG) {
891 891
                 $msg =
892 892
                     sprintf(
@@ -912,7 +912,7 @@  discard block
 block discarded – undo
912 912
         $full_dest_path = EEH_File::standardise_directory_separators($destination_file);
913 913
         $folder         = EEH_File::remove_filename_from_filepath($full_dest_path);
914 914
         EEH_File::ensure_folder_exists_and_is_writable($folder);
915
-        if (! EEH_File::verify_is_writable($folder, 'folder')) {
915
+        if ( ! EEH_File::verify_is_writable($folder, 'folder')) {
916 916
             if (defined('WP_DEBUG') && WP_DEBUG) {
917 917
                 $msg = sprintf(
918 918
                     __('The file located at "%2$s" is not writable.', 'event_espresso'),
Please login to merge, or discard this patch.
core/EE_Dependency_Map.core.php 1 patch
Indentation   +990 added lines, -990 removed lines patch added patch discarded remove patch
@@ -21,994 +21,994 @@
 block discarded – undo
21 21
 class EE_Dependency_Map
22 22
 {
23 23
 
24
-    /**
25
-     * This means that the requested class dependency is not present in the dependency map
26
-     */
27
-    const not_registered = 0;
28
-
29
-    /**
30
-     * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
31
-     */
32
-    const load_new_object = 1;
33
-
34
-    /**
35
-     * This instructs class loaders to return a previously instantiated and cached object for the requested class.
36
-     * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
37
-     */
38
-    const load_from_cache = 2;
39
-
40
-    /**
41
-     * When registering a dependency,
42
-     * this indicates to keep any existing dependencies that already exist,
43
-     * and simply discard any new dependencies declared in the incoming data
44
-     */
45
-    const KEEP_EXISTING_DEPENDENCIES = 0;
46
-
47
-    /**
48
-     * When registering a dependency,
49
-     * this indicates to overwrite any existing dependencies that already exist using the incoming data
50
-     */
51
-    const OVERWRITE_DEPENDENCIES = 1;
52
-
53
-    /**
54
-     * @type EE_Dependency_Map $_instance
55
-     */
56
-    protected static $_instance;
57
-
58
-    /**
59
-     * @var ClassInterfaceCache $class_cache
60
-     */
61
-    private $class_cache;
62
-
63
-    /**
64
-     * @type RequestInterface $request
65
-     */
66
-    protected $request;
67
-
68
-    /**
69
-     * @type LegacyRequestInterface $legacy_request
70
-     */
71
-    protected $legacy_request;
72
-
73
-    /**
74
-     * @type ResponseInterface $response
75
-     */
76
-    protected $response;
77
-
78
-    /**
79
-     * @type LoaderInterface $loader
80
-     */
81
-    protected $loader;
82
-
83
-    /**
84
-     * @type array $_dependency_map
85
-     */
86
-    protected $_dependency_map = [];
87
-
88
-    /**
89
-     * @type array $_class_loaders
90
-     */
91
-    protected $_class_loaders = [];
92
-
93
-
94
-    /**
95
-     * EE_Dependency_Map constructor.
96
-     *
97
-     * @param ClassInterfaceCache $class_cache
98
-     */
99
-    protected function __construct(ClassInterfaceCache $class_cache)
100
-    {
101
-        $this->class_cache = $class_cache;
102
-        do_action('EE_Dependency_Map____construct', $this);
103
-    }
104
-
105
-
106
-    /**
107
-     * @return void
108
-     * @throws InvalidAliasException
109
-     */
110
-    public function initialize()
111
-    {
112
-        $this->_register_core_dependencies();
113
-        $this->_register_core_class_loaders();
114
-        $this->_register_core_aliases();
115
-    }
116
-
117
-
118
-    /**
119
-     * @singleton method used to instantiate class object
120
-     * @param ClassInterfaceCache|null $class_cache
121
-     * @return EE_Dependency_Map
122
-     */
123
-    public static function instance(ClassInterfaceCache $class_cache = null)
124
-    {
125
-        // check if class object is instantiated, and instantiated properly
126
-        if (! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
127
-            && $class_cache instanceof ClassInterfaceCache
128
-        ) {
129
-            EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
130
-        }
131
-        return EE_Dependency_Map::$_instance;
132
-    }
133
-
134
-
135
-    /**
136
-     * @param RequestInterface $request
137
-     */
138
-    public function setRequest(RequestInterface $request)
139
-    {
140
-        $this->request = $request;
141
-    }
142
-
143
-
144
-    /**
145
-     * @param LegacyRequestInterface $legacy_request
146
-     */
147
-    public function setLegacyRequest(LegacyRequestInterface $legacy_request)
148
-    {
149
-        $this->legacy_request = $legacy_request;
150
-    }
151
-
152
-
153
-    /**
154
-     * @param ResponseInterface $response
155
-     */
156
-    public function setResponse(ResponseInterface $response)
157
-    {
158
-        $this->response = $response;
159
-    }
160
-
161
-
162
-    /**
163
-     * @param LoaderInterface $loader
164
-     */
165
-    public function setLoader(LoaderInterface $loader)
166
-    {
167
-        $this->loader = $loader;
168
-    }
169
-
170
-
171
-    /**
172
-     * @param string $class
173
-     * @param array  $dependencies
174
-     * @param int    $overwrite
175
-     * @return bool
176
-     */
177
-    public static function register_dependencies(
178
-        $class,
179
-        array $dependencies,
180
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
181
-    ) {
182
-        return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
183
-    }
184
-
185
-
186
-    /**
187
-     * Assigns an array of class names and corresponding load sources (new or cached)
188
-     * to the class specified by the first parameter.
189
-     * IMPORTANT !!!
190
-     * The order of elements in the incoming $dependencies array MUST match
191
-     * the order of the constructor parameters for the class in question.
192
-     * This is especially important when overriding any existing dependencies that are registered.
193
-     * the third parameter controls whether any duplicate dependencies are overwritten or not.
194
-     *
195
-     * @param string $class
196
-     * @param array  $dependencies
197
-     * @param int    $overwrite
198
-     * @return bool
199
-     */
200
-    public function registerDependencies(
201
-        $class,
202
-        array $dependencies,
203
-        $overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
204
-    ) {
205
-        $class = trim($class, '\\');
206
-        $registered = false;
207
-        if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
208
-            EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
209
-        }
210
-        // we need to make sure that any aliases used when registering a dependency
211
-        // get resolved to the correct class name
212
-        foreach ($dependencies as $dependency => $load_source) {
213
-            $alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
214
-            if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
215
-                || ! isset(EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ])
216
-            ) {
217
-                unset($dependencies[ $dependency ]);
218
-                $dependencies[ $alias ] = $load_source;
219
-                $registered = true;
220
-            }
221
-        }
222
-        // now add our two lists of dependencies together.
223
-        // using Union (+=) favours the arrays in precedence from left to right,
224
-        // so $dependencies is NOT overwritten because it is listed first
225
-        // ie: with A = B + C, entries in B take precedence over duplicate entries in C
226
-        // Union is way faster than array_merge() but should be used with caution...
227
-        // especially with numerically indexed arrays
228
-        $dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
229
-        // now we need to ensure that the resulting dependencies
230
-        // array only has the entries that are required for the class
231
-        // so first count how many dependencies were originally registered for the class
232
-        $dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
233
-        // if that count is non-zero (meaning dependencies were already registered)
234
-        EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
235
-            // then truncate the  final array to match that count
236
-            ? array_slice($dependencies, 0, $dependency_count)
237
-            // otherwise just take the incoming array because nothing previously existed
238
-            : $dependencies;
239
-        return $registered;
240
-    }
241
-
242
-
243
-    /**
244
-     * @param string $class_name
245
-     * @param string $loader
246
-     * @return bool
247
-     * @throws DomainException
248
-     */
249
-    public static function register_class_loader($class_name, $loader = 'load_core')
250
-    {
251
-        return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader);
252
-    }
253
-
254
-
255
-    /**
256
-     * @param string $class_name
257
-     * @param string $loader
258
-     * @return bool
259
-     * @throws DomainException
260
-     */
261
-    public function registerClassLoader($class_name, $loader = 'load_core')
262
-    {
263
-        if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
264
-            throw new DomainException(
265
-                esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
266
-            );
267
-        }
268
-        // check that loader is callable or method starts with "load_" and exists in EE_Registry
269
-        if (! is_callable($loader)
270
-            && (
271
-                strpos($loader, 'load_') !== 0
272
-                || ! method_exists('EE_Registry', $loader)
273
-            )
274
-        ) {
275
-            throw new DomainException(
276
-                sprintf(
277
-                    esc_html__(
278
-                        '"%1$s" is not a valid loader method on EE_Registry.',
279
-                        'event_espresso'
280
-                    ),
281
-                    $loader
282
-                )
283
-            );
284
-        }
285
-        $class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
286
-        if (! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
287
-            EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
288
-            return true;
289
-        }
290
-        return false;
291
-    }
292
-
293
-
294
-    /**
295
-     * @return array
296
-     */
297
-    public function dependency_map()
298
-    {
299
-        return $this->_dependency_map;
300
-    }
301
-
302
-
303
-    /**
304
-     * returns TRUE if dependency map contains a listing for the provided class name
305
-     *
306
-     * @param string $class_name
307
-     * @return boolean
308
-     */
309
-    public function has($class_name = '')
310
-    {
311
-        // all legacy models have the same dependencies
312
-        if (strpos($class_name, 'EEM_') === 0) {
313
-            $class_name = 'LEGACY_MODELS';
314
-        }
315
-        return isset($this->_dependency_map[ $class_name ]);
316
-    }
317
-
318
-
319
-    /**
320
-     * returns TRUE if dependency map contains a listing for the provided class name AND dependency
321
-     *
322
-     * @param string $class_name
323
-     * @param string $dependency
324
-     * @return bool
325
-     */
326
-    public function has_dependency_for_class($class_name = '', $dependency = '')
327
-    {
328
-        // all legacy models have the same dependencies
329
-        if (strpos($class_name, 'EEM_') === 0) {
330
-            $class_name = 'LEGACY_MODELS';
331
-        }
332
-        $dependency = $this->getFqnForAlias($dependency, $class_name);
333
-        return isset($this->_dependency_map[ $class_name ][ $dependency ]);
334
-    }
335
-
336
-
337
-    /**
338
-     * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
339
-     *
340
-     * @param string $class_name
341
-     * @param string $dependency
342
-     * @return int
343
-     */
344
-    public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
345
-    {
346
-        // all legacy models have the same dependencies
347
-        if (strpos($class_name, 'EEM_') === 0) {
348
-            $class_name = 'LEGACY_MODELS';
349
-        }
350
-        $dependency = $this->getFqnForAlias($dependency);
351
-        return $this->has_dependency_for_class($class_name, $dependency)
352
-            ? $this->_dependency_map[ $class_name ][ $dependency ]
353
-            : EE_Dependency_Map::not_registered;
354
-    }
355
-
356
-
357
-    /**
358
-     * @param string $class_name
359
-     * @return string | Closure
360
-     */
361
-    public function class_loader($class_name)
362
-    {
363
-        // all legacy models use load_model()
364
-        if (strpos($class_name, 'EEM_') === 0) {
365
-            return 'load_model';
366
-        }
367
-        // EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
368
-        // perform strpos() first to avoid loading regex every time we load a class
369
-        if (strpos($class_name, 'EE_CPT_') === 0
370
-            && preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
371
-        ) {
372
-            return 'load_core';
373
-        }
374
-        $class_name = $this->getFqnForAlias($class_name);
375
-        return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
376
-    }
377
-
378
-
379
-    /**
380
-     * @return array
381
-     */
382
-    public function class_loaders()
383
-    {
384
-        return $this->_class_loaders;
385
-    }
386
-
387
-
388
-    /**
389
-     * adds an alias for a classname
390
-     *
391
-     * @param string $fqcn      the class name that should be used (concrete class to replace interface)
392
-     * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
393
-     * @param string $for_class the class that has the dependency (is type hinting for the interface)
394
-     * @throws InvalidAliasException
395
-     */
396
-    public function add_alias($fqcn, $alias, $for_class = '')
397
-    {
398
-        $this->class_cache->addAlias($fqcn, $alias, $for_class);
399
-    }
400
-
401
-
402
-    /**
403
-     * Returns TRUE if the provided fully qualified name IS an alias
404
-     * WHY?
405
-     * Because if a class is type hinting for a concretion,
406
-     * then why would we need to find another class to supply it?
407
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
408
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
409
-     * Don't go looking for some substitute.
410
-     * Whereas if a class is type hinting for an interface...
411
-     * then we need to find an actual class to use.
412
-     * So the interface IS the alias for some other FQN,
413
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
414
-     * represents some other class.
415
-     *
416
-     * @param string $fqn
417
-     * @param string $for_class
418
-     * @return bool
419
-     */
420
-    public function isAlias($fqn = '', $for_class = '')
421
-    {
422
-        return $this->class_cache->isAlias($fqn, $for_class);
423
-    }
424
-
425
-
426
-    /**
427
-     * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
428
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
429
-     *  for example:
430
-     *      if the following two entries were added to the _aliases array:
431
-     *          array(
432
-     *              'interface_alias'           => 'some\namespace\interface'
433
-     *              'some\namespace\interface'  => 'some\namespace\classname'
434
-     *          )
435
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
436
-     *      to load an instance of 'some\namespace\classname'
437
-     *
438
-     * @param string $alias
439
-     * @param string $for_class
440
-     * @return string
441
-     */
442
-    public function getFqnForAlias($alias = '', $for_class = '')
443
-    {
444
-        return (string) $this->class_cache->getFqnForAlias($alias, $for_class);
445
-    }
446
-
447
-
448
-    /**
449
-     * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
450
-     * if one exists, or whether a new object should be generated every time the requested class is loaded.
451
-     * This is done by using the following class constants:
452
-     *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
453
-     *        EE_Dependency_Map::load_new_object - generates a new object every time
454
-     */
455
-    protected function _register_core_dependencies()
456
-    {
457
-        $this->_dependency_map = [
458
-            'EE_Request_Handler'                                                                                          => [
459
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
460
-            ],
461
-            'EE_System'                                                                                                   => [
462
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
463
-                'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
464
-                'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
465
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
466
-                'EventEspresso\core\services\routing\Router'  => EE_Dependency_Map::load_from_cache,
467
-            ],
468
-            'EE_Admin'                                                                                                    => [
469
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
470
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
471
-            ],
472
-            'EE_Cart'                                                                                                     => [
473
-                'EE_Session' => EE_Dependency_Map::load_from_cache,
474
-            ],
475
-            'EE_Messenger_Collection_Loader'                                                                              => [
476
-                'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
477
-            ],
478
-            'EE_Message_Type_Collection_Loader'                                                                           => [
479
-                'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
480
-            ],
481
-            'EE_Message_Resource_Manager'                                                                                 => [
482
-                'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
483
-                'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
484
-                'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
485
-            ],
486
-            'EE_Message_Factory'                                                                                          => [
487
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
488
-            ],
489
-            'EE_messages'                                                                                                 => [
490
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
491
-            ],
492
-            'EE_Messages_Generator'                                                                                       => [
493
-                'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
494
-                'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
495
-                'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
496
-                'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
497
-            ],
498
-            'EE_Messages_Processor'                                                                                       => [
499
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
500
-            ],
501
-            'EE_Messages_Queue'                                                                                           => [
502
-                'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
503
-            ],
504
-            'EE_Messages_Template_Defaults'                                                                               => [
505
-                'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
506
-                'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
507
-            ],
508
-            'EE_Message_To_Generate_From_Request'                                                                         => [
509
-                'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
510
-                'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
511
-            ],
512
-            'EventEspresso\core\services\commands\CommandBus'                                                             => [
513
-                'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
514
-            ],
515
-            'EventEspresso\services\commands\CommandHandler'                                                              => [
516
-                'EE_Registry'         => EE_Dependency_Map::load_from_cache,
517
-                'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
518
-            ],
519
-            'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => [
520
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
521
-            ],
522
-            'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => [
523
-                'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
524
-                'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
525
-            ],
526
-            'EventEspresso\core\services\commands\CommandFactory'                                                         => [
527
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
528
-            ],
529
-            'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => [
530
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
531
-            ],
532
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => [
533
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
534
-            ],
535
-            'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => [
536
-                'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
537
-            ],
538
-            'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => [
539
-                'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
540
-            ],
541
-            'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
542
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
543
-            ],
544
-            'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
545
-                'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
546
-            ],
547
-            'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
548
-                'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
549
-            ],
550
-            'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
551
-                'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
552
-            ],
553
-            'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
554
-                'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
555
-            ],
556
-            'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
557
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
558
-            ],
559
-            'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => [
560
-                'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
561
-            ],
562
-            'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
563
-                'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
564
-            ],
565
-            'EventEspresso\core\services\database\TableManager'                                                           => [
566
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
567
-            ],
568
-            'EE_Data_Migration_Class_Base'                                                                                => [
569
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
570
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
571
-            ],
572
-            'EE_DMS_Core_4_1_0'                                                                                           => [
573
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
574
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
575
-            ],
576
-            'EE_DMS_Core_4_2_0'                                                                                           => [
577
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
578
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
579
-            ],
580
-            'EE_DMS_Core_4_3_0'                                                                                           => [
581
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
582
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
583
-            ],
584
-            'EE_DMS_Core_4_4_0'                                                                                           => [
585
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
586
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
587
-            ],
588
-            'EE_DMS_Core_4_5_0'                                                                                           => [
589
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
590
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
591
-            ],
592
-            'EE_DMS_Core_4_6_0'                                                                                           => [
593
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
594
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
595
-            ],
596
-            'EE_DMS_Core_4_7_0'                                                                                           => [
597
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
598
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
599
-            ],
600
-            'EE_DMS_Core_4_8_0'                                                                                           => [
601
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
602
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
603
-            ],
604
-            'EE_DMS_Core_4_9_0'                                                                                           => [
605
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
606
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
607
-            ],
608
-            'EE_DMS_Core_4_10_0'                                                                                          => [
609
-                'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
610
-                'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
611
-                'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
612
-            ],
613
-            'EventEspresso\core\services\assets\I18nRegistry'                                                             => [
614
-                'EventEspresso\core\domain\Domain'                 => EE_Dependency_Map::load_from_cache,
615
-                'EventEspresso\core\services\assets\JedLocaleData' => EE_Dependency_Map::load_from_cache,
616
-                [],
617
-            ],
618
-            'EventEspresso\core\services\assets\Registry'                                                                 => [
619
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
620
-                'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
621
-            ],
622
-            'EventEspresso\core\services\cache\BasicCacheManager'                                                         => [
623
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
624
-            ],
625
-            'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => [
626
-                'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
627
-            ],
628
-            'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => [
629
-                'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
630
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
631
-            ],
632
-            'EventEspresso\core\domain\values\EmailAddress'                                                               => [
633
-                null,
634
-                'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
635
-            ],
636
-            'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => [
637
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
638
-            ],
639
-            'LEGACY_MODELS'                                                                                               => [
640
-                null,
641
-                'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
642
-            ],
643
-            'EE_Module_Request_Router'                                                                                    => [
644
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
645
-            ],
646
-            'EE_Registration_Processor'                                                                                   => [
647
-                'EE_Request' => EE_Dependency_Map::load_from_cache,
648
-            ],
649
-            'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => [
650
-                null,
651
-                'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
652
-                'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
653
-            ],
654
-            'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => [
655
-                'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
656
-                'EE_Session'             => EE_Dependency_Map::load_from_cache,
657
-            ],
658
-            'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => [
659
-                'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
660
-                'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
661
-                'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
662
-                'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
663
-                'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
664
-            ],
665
-            'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => [
666
-                'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
667
-            ],
668
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => [
669
-                'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
670
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
671
-            ],
672
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => [
673
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
674
-            ],
675
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => [
676
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
677
-            ],
678
-            'EE_CPT_Strategy'                                                                                             => [
679
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
680
-                'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
681
-            ],
682
-            'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => [
683
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
684
-            ],
685
-            'EventEspresso\core\CPTs\CptQueryModifier'                                                                    => [
686
-                null,
687
-                null,
688
-                null,
689
-                'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
690
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
691
-                'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
692
-            ],
693
-            'EventEspresso\core\services\dependencies\DependencyResolver'                                                 => [
694
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
695
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
696
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
697
-            ],
698
-            'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                               => [
699
-                'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
700
-                'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
701
-                'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
702
-            ],
703
-            'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                          => [
704
-                'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
705
-                'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
706
-            ],
707
-            'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                          => [
708
-                'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
709
-                'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
710
-            ],
711
-            'EE_URL_Validation_Strategy'                                                                                  => [
712
-                null,
713
-                null,
714
-                'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache,
715
-            ],
716
-            'EventEspresso\core\services\request\files\FilesDataHandler'                                                  => [
717
-                'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
718
-            ],
719
-            'EventEspressoBatchRequest\BatchRequestProcessor'                                                             => [
720
-                'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
721
-            ],
722
-            'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                => [
723
-                'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
724
-                'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
725
-                'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
726
-                null,
727
-            ],
728
-            'EventEspresso\core\services\routing\RouteHandler'                                                            => [
729
-                'EventEspresso\core\services\json\JsonDataNodeHandler' => EE_Dependency_Map::load_from_cache,
730
-                'EventEspresso\core\services\loaders\Loader'           => EE_Dependency_Map::load_from_cache,
731
-                'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
732
-                'EventEspresso\core\services\routing\RouteCollection'  => EE_Dependency_Map::load_from_cache,
733
-            ],
734
-            'EventEspresso\core\services\json\JsonDataNodeHandler'                                                        => [
735
-                'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
736
-            ],
737
-            'EventEspresso\core\domain\services\assets\EspressoCoreAppAssetManager'                                       => [
738
-                'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
739
-                'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
740
-                'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
741
-            ],
742
-            'EventEspresso\core\services\routing\Router'                                                                  => [
743
-                'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
744
-                'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
745
-                'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
746
-            ],
747
-        ];
748
-    }
749
-
750
-
751
-    /**
752
-     * Registers how core classes are loaded.
753
-     * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
754
-     *        'EE_Request_Handler' => 'load_core'
755
-     *        'EE_Messages_Queue'  => 'load_lib'
756
-     *        'EEH_Debug_Tools'    => 'load_helper'
757
-     * or, if greater control is required, by providing a custom closure. For example:
758
-     *        'Some_Class' => function () {
759
-     *            return new Some_Class();
760
-     *        },
761
-     * This is required for instantiating dependencies
762
-     * where an interface has been type hinted in a class constructor. For example:
763
-     *        'Required_Interface' => function () {
764
-     *            return new A_Class_That_Implements_Required_Interface();
765
-     *        },
766
-     */
767
-    protected function _register_core_class_loaders()
768
-    {
769
-        $this->_class_loaders = [
770
-            // load_core
771
-            'EE_Dependency_Map'                            => function () {
772
-                return $this;
773
-            },
774
-            'EE_Capabilities'                              => 'load_core',
775
-            'EE_Encryption'                                => 'load_core',
776
-            'EE_Front_Controller'                          => 'load_core',
777
-            'EE_Module_Request_Router'                     => 'load_core',
778
-            'EE_Registry'                                  => 'load_core',
779
-            'EE_Request'                                   => function () {
780
-                return $this->legacy_request;
781
-            },
782
-            'EventEspresso\core\services\request\Request'  => function () {
783
-                return $this->request;
784
-            },
785
-            'EventEspresso\core\services\request\Response' => function () {
786
-                return $this->response;
787
-            },
788
-            'EE_Base'                                      => 'load_core',
789
-            'EE_Request_Handler'                           => 'load_core',
790
-            'EE_Session'                                   => 'load_core',
791
-            'EE_Cron_Tasks'                                => 'load_core',
792
-            'EE_System'                                    => 'load_core',
793
-            'EE_Maintenance_Mode'                          => 'load_core',
794
-            'EE_Register_CPTs'                             => 'load_core',
795
-            'EE_Admin'                                     => 'load_core',
796
-            'EE_CPT_Strategy'                              => 'load_core',
797
-            // load_class
798
-            'EE_Registration_Processor'                    => 'load_class',
799
-            // load_lib
800
-            'EE_Message_Resource_Manager'                  => 'load_lib',
801
-            'EE_Message_Type_Collection'                   => 'load_lib',
802
-            'EE_Message_Type_Collection_Loader'            => 'load_lib',
803
-            'EE_Messenger_Collection'                      => 'load_lib',
804
-            'EE_Messenger_Collection_Loader'               => 'load_lib',
805
-            'EE_Messages_Processor'                        => 'load_lib',
806
-            'EE_Message_Repository'                        => 'load_lib',
807
-            'EE_Messages_Queue'                            => 'load_lib',
808
-            'EE_Messages_Data_Handler_Collection'          => 'load_lib',
809
-            'EE_Message_Template_Group_Collection'         => 'load_lib',
810
-            'EE_Payment_Method_Manager'                    => 'load_lib',
811
-            'EE_DMS_Core_4_1_0'                            => 'load_dms',
812
-            'EE_DMS_Core_4_2_0'                            => 'load_dms',
813
-            'EE_DMS_Core_4_3_0'                            => 'load_dms',
814
-            'EE_DMS_Core_4_5_0'                            => 'load_dms',
815
-            'EE_DMS_Core_4_6_0'                            => 'load_dms',
816
-            'EE_DMS_Core_4_7_0'                            => 'load_dms',
817
-            'EE_DMS_Core_4_8_0'                            => 'load_dms',
818
-            'EE_DMS_Core_4_9_0'                            => 'load_dms',
819
-            'EE_DMS_Core_4_10_0'                           => 'load_dms',
820
-            'EE_Messages_Generator'                        => static function () {
821
-                return EE_Registry::instance()->load_lib(
822
-                    'Messages_Generator',
823
-                    [],
824
-                    false,
825
-                    false
826
-                );
827
-            },
828
-            'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
829
-                return EE_Registry::instance()->load_lib(
830
-                    'Messages_Template_Defaults',
831
-                    $arguments,
832
-                    false,
833
-                    false
834
-                );
835
-            },
836
-            // load_helper
837
-            'EEH_Parse_Shortcodes'                         => static function () {
838
-                if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
839
-                    return new EEH_Parse_Shortcodes();
840
-                }
841
-                return null;
842
-            },
843
-            'EE_Template_Config'                           => static function () {
844
-                return EE_Config::instance()->template_settings;
845
-            },
846
-            'EE_Currency_Config'                           => static function () {
847
-                return EE_Config::instance()->currency;
848
-            },
849
-            'EE_Registration_Config'                       => static function () {
850
-                return EE_Config::instance()->registration;
851
-            },
852
-            'EE_Core_Config'                               => static function () {
853
-                return EE_Config::instance()->core;
854
-            },
855
-            'EventEspresso\core\services\loaders\Loader'   => static function () {
856
-                return LoaderFactory::getLoader();
857
-            },
858
-            'EE_Network_Config'                            => static function () {
859
-                return EE_Network_Config::instance();
860
-            },
861
-            'EE_Config'                                    => static function () {
862
-                return EE_Config::instance();
863
-            },
864
-            'EventEspresso\core\domain\Domain'             => static function () {
865
-                return DomainFactory::getEventEspressoCoreDomain();
866
-            },
867
-            'EE_Admin_Config'                              => static function () {
868
-                return EE_Config::instance()->admin;
869
-            },
870
-            'EE_Organization_Config'                       => static function () {
871
-                return EE_Config::instance()->organization;
872
-            },
873
-            'EE_Network_Core_Config'                       => static function () {
874
-                return EE_Network_Config::instance()->core;
875
-            },
876
-            'EE_Environment_Config'                        => static function () {
877
-                return EE_Config::instance()->environment;
878
-            },
879
-            'EED_Core_Rest_Api'                            => static function () {
880
-                return EED_Core_Rest_Api::instance();
881
-            },
882
-            'WP_REST_Server'                               => static function () {
883
-                return rest_get_server();
884
-            },
885
-        ];
886
-    }
887
-
888
-
889
-    /**
890
-     * can be used for supplying alternate names for classes,
891
-     * or for connecting interface names to instantiable classes
892
-     *
893
-     * @throws InvalidAliasException
894
-     */
895
-    protected function _register_core_aliases()
896
-    {
897
-        $aliases = [
898
-            'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
899
-            'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
900
-            'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
901
-            'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
902
-            'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
903
-            'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
904
-            'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
905
-            'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
906
-            'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
907
-            'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
908
-            'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
909
-            'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
910
-            'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
911
-            'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
912
-            'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
913
-            'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
914
-            'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
915
-            'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
916
-            'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
917
-            'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
918
-            'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
919
-            'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
920
-            'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
921
-            'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
922
-            'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
923
-            'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
924
-            'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
925
-            'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
926
-            'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
927
-            'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
928
-            'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
929
-            'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
930
-            'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
931
-            'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
932
-            'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
933
-            'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
934
-            'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
935
-            'Registration_Processor'                                                       => 'EE_Registration_Processor',
936
-        ];
937
-        foreach ($aliases as $alias => $fqn) {
938
-            if (is_array($fqn)) {
939
-                foreach ($fqn as $class => $for_class) {
940
-                    $this->class_cache->addAlias($class, $alias, $for_class);
941
-                }
942
-                continue;
943
-            }
944
-            $this->class_cache->addAlias($fqn, $alias);
945
-        }
946
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
947
-            $this->class_cache->addAlias(
948
-                'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
949
-                'EventEspresso\core\services\notices\NoticeConverterInterface'
950
-            );
951
-        }
952
-    }
953
-
954
-
955
-    /**
956
-     * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
957
-     * request Primarily used by unit tests.
958
-     */
959
-    public function reset()
960
-    {
961
-        $this->_register_core_class_loaders();
962
-        $this->_register_core_dependencies();
963
-    }
964
-
965
-
966
-    /**
967
-     * PLZ NOTE: a better name for this method would be is_alias()
968
-     * because it returns TRUE if the provided fully qualified name IS an alias
969
-     * WHY?
970
-     * Because if a class is type hinting for a concretion,
971
-     * then why would we need to find another class to supply it?
972
-     * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
973
-     * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
974
-     * Don't go looking for some substitute.
975
-     * Whereas if a class is type hinting for an interface...
976
-     * then we need to find an actual class to use.
977
-     * So the interface IS the alias for some other FQN,
978
-     * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
979
-     * represents some other class.
980
-     *
981
-     * @param string $fqn
982
-     * @param string $for_class
983
-     * @return bool
984
-     * @deprecated 4.9.62.p
985
-     */
986
-    public function has_alias($fqn = '', $for_class = '')
987
-    {
988
-        return $this->isAlias($fqn, $for_class);
989
-    }
990
-
991
-
992
-    /**
993
-     * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
994
-     * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
995
-     * functions recursively, so that multiple aliases can be used to drill down to a FQN
996
-     *  for example:
997
-     *      if the following two entries were added to the _aliases array:
998
-     *          array(
999
-     *              'interface_alias'           => 'some\namespace\interface'
1000
-     *              'some\namespace\interface'  => 'some\namespace\classname'
1001
-     *          )
1002
-     *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1003
-     *      to load an instance of 'some\namespace\classname'
1004
-     *
1005
-     * @param string $alias
1006
-     * @param string $for_class
1007
-     * @return string
1008
-     * @deprecated 4.9.62.p
1009
-     */
1010
-    public function get_alias($alias = '', $for_class = '')
1011
-    {
1012
-        return $this->getFqnForAlias($alias, $for_class);
1013
-    }
24
+	/**
25
+	 * This means that the requested class dependency is not present in the dependency map
26
+	 */
27
+	const not_registered = 0;
28
+
29
+	/**
30
+	 * This instructs class loaders to ALWAYS return a newly instantiated object for the requested class.
31
+	 */
32
+	const load_new_object = 1;
33
+
34
+	/**
35
+	 * This instructs class loaders to return a previously instantiated and cached object for the requested class.
36
+	 * IF a previously instantiated object does not exist, a new one will be created and added to the cache.
37
+	 */
38
+	const load_from_cache = 2;
39
+
40
+	/**
41
+	 * When registering a dependency,
42
+	 * this indicates to keep any existing dependencies that already exist,
43
+	 * and simply discard any new dependencies declared in the incoming data
44
+	 */
45
+	const KEEP_EXISTING_DEPENDENCIES = 0;
46
+
47
+	/**
48
+	 * When registering a dependency,
49
+	 * this indicates to overwrite any existing dependencies that already exist using the incoming data
50
+	 */
51
+	const OVERWRITE_DEPENDENCIES = 1;
52
+
53
+	/**
54
+	 * @type EE_Dependency_Map $_instance
55
+	 */
56
+	protected static $_instance;
57
+
58
+	/**
59
+	 * @var ClassInterfaceCache $class_cache
60
+	 */
61
+	private $class_cache;
62
+
63
+	/**
64
+	 * @type RequestInterface $request
65
+	 */
66
+	protected $request;
67
+
68
+	/**
69
+	 * @type LegacyRequestInterface $legacy_request
70
+	 */
71
+	protected $legacy_request;
72
+
73
+	/**
74
+	 * @type ResponseInterface $response
75
+	 */
76
+	protected $response;
77
+
78
+	/**
79
+	 * @type LoaderInterface $loader
80
+	 */
81
+	protected $loader;
82
+
83
+	/**
84
+	 * @type array $_dependency_map
85
+	 */
86
+	protected $_dependency_map = [];
87
+
88
+	/**
89
+	 * @type array $_class_loaders
90
+	 */
91
+	protected $_class_loaders = [];
92
+
93
+
94
+	/**
95
+	 * EE_Dependency_Map constructor.
96
+	 *
97
+	 * @param ClassInterfaceCache $class_cache
98
+	 */
99
+	protected function __construct(ClassInterfaceCache $class_cache)
100
+	{
101
+		$this->class_cache = $class_cache;
102
+		do_action('EE_Dependency_Map____construct', $this);
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return void
108
+	 * @throws InvalidAliasException
109
+	 */
110
+	public function initialize()
111
+	{
112
+		$this->_register_core_dependencies();
113
+		$this->_register_core_class_loaders();
114
+		$this->_register_core_aliases();
115
+	}
116
+
117
+
118
+	/**
119
+	 * @singleton method used to instantiate class object
120
+	 * @param ClassInterfaceCache|null $class_cache
121
+	 * @return EE_Dependency_Map
122
+	 */
123
+	public static function instance(ClassInterfaceCache $class_cache = null)
124
+	{
125
+		// check if class object is instantiated, and instantiated properly
126
+		if (! EE_Dependency_Map::$_instance instanceof EE_Dependency_Map
127
+			&& $class_cache instanceof ClassInterfaceCache
128
+		) {
129
+			EE_Dependency_Map::$_instance = new EE_Dependency_Map($class_cache);
130
+		}
131
+		return EE_Dependency_Map::$_instance;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @param RequestInterface $request
137
+	 */
138
+	public function setRequest(RequestInterface $request)
139
+	{
140
+		$this->request = $request;
141
+	}
142
+
143
+
144
+	/**
145
+	 * @param LegacyRequestInterface $legacy_request
146
+	 */
147
+	public function setLegacyRequest(LegacyRequestInterface $legacy_request)
148
+	{
149
+		$this->legacy_request = $legacy_request;
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param ResponseInterface $response
155
+	 */
156
+	public function setResponse(ResponseInterface $response)
157
+	{
158
+		$this->response = $response;
159
+	}
160
+
161
+
162
+	/**
163
+	 * @param LoaderInterface $loader
164
+	 */
165
+	public function setLoader(LoaderInterface $loader)
166
+	{
167
+		$this->loader = $loader;
168
+	}
169
+
170
+
171
+	/**
172
+	 * @param string $class
173
+	 * @param array  $dependencies
174
+	 * @param int    $overwrite
175
+	 * @return bool
176
+	 */
177
+	public static function register_dependencies(
178
+		$class,
179
+		array $dependencies,
180
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
181
+	) {
182
+		return EE_Dependency_Map::$_instance->registerDependencies($class, $dependencies, $overwrite);
183
+	}
184
+
185
+
186
+	/**
187
+	 * Assigns an array of class names and corresponding load sources (new or cached)
188
+	 * to the class specified by the first parameter.
189
+	 * IMPORTANT !!!
190
+	 * The order of elements in the incoming $dependencies array MUST match
191
+	 * the order of the constructor parameters for the class in question.
192
+	 * This is especially important when overriding any existing dependencies that are registered.
193
+	 * the third parameter controls whether any duplicate dependencies are overwritten or not.
194
+	 *
195
+	 * @param string $class
196
+	 * @param array  $dependencies
197
+	 * @param int    $overwrite
198
+	 * @return bool
199
+	 */
200
+	public function registerDependencies(
201
+		$class,
202
+		array $dependencies,
203
+		$overwrite = EE_Dependency_Map::KEEP_EXISTING_DEPENDENCIES
204
+	) {
205
+		$class = trim($class, '\\');
206
+		$registered = false;
207
+		if (empty(EE_Dependency_Map::$_instance->_dependency_map[ $class ])) {
208
+			EE_Dependency_Map::$_instance->_dependency_map[ $class ] = [];
209
+		}
210
+		// we need to make sure that any aliases used when registering a dependency
211
+		// get resolved to the correct class name
212
+		foreach ($dependencies as $dependency => $load_source) {
213
+			$alias = EE_Dependency_Map::$_instance->getFqnForAlias($dependency);
214
+			if ($overwrite === EE_Dependency_Map::OVERWRITE_DEPENDENCIES
215
+				|| ! isset(EE_Dependency_Map::$_instance->_dependency_map[ $class ][ $alias ])
216
+			) {
217
+				unset($dependencies[ $dependency ]);
218
+				$dependencies[ $alias ] = $load_source;
219
+				$registered = true;
220
+			}
221
+		}
222
+		// now add our two lists of dependencies together.
223
+		// using Union (+=) favours the arrays in precedence from left to right,
224
+		// so $dependencies is NOT overwritten because it is listed first
225
+		// ie: with A = B + C, entries in B take precedence over duplicate entries in C
226
+		// Union is way faster than array_merge() but should be used with caution...
227
+		// especially with numerically indexed arrays
228
+		$dependencies += EE_Dependency_Map::$_instance->_dependency_map[ $class ];
229
+		// now we need to ensure that the resulting dependencies
230
+		// array only has the entries that are required for the class
231
+		// so first count how many dependencies were originally registered for the class
232
+		$dependency_count = count(EE_Dependency_Map::$_instance->_dependency_map[ $class ]);
233
+		// if that count is non-zero (meaning dependencies were already registered)
234
+		EE_Dependency_Map::$_instance->_dependency_map[ $class ] = $dependency_count
235
+			// then truncate the  final array to match that count
236
+			? array_slice($dependencies, 0, $dependency_count)
237
+			// otherwise just take the incoming array because nothing previously existed
238
+			: $dependencies;
239
+		return $registered;
240
+	}
241
+
242
+
243
+	/**
244
+	 * @param string $class_name
245
+	 * @param string $loader
246
+	 * @return bool
247
+	 * @throws DomainException
248
+	 */
249
+	public static function register_class_loader($class_name, $loader = 'load_core')
250
+	{
251
+		return EE_Dependency_Map::$_instance->registerClassLoader($class_name, $loader);
252
+	}
253
+
254
+
255
+	/**
256
+	 * @param string $class_name
257
+	 * @param string $loader
258
+	 * @return bool
259
+	 * @throws DomainException
260
+	 */
261
+	public function registerClassLoader($class_name, $loader = 'load_core')
262
+	{
263
+		if (! $loader instanceof Closure && strpos($class_name, '\\') !== false) {
264
+			throw new DomainException(
265
+				esc_html__('Don\'t use class loaders for FQCNs.', 'event_espresso')
266
+			);
267
+		}
268
+		// check that loader is callable or method starts with "load_" and exists in EE_Registry
269
+		if (! is_callable($loader)
270
+			&& (
271
+				strpos($loader, 'load_') !== 0
272
+				|| ! method_exists('EE_Registry', $loader)
273
+			)
274
+		) {
275
+			throw new DomainException(
276
+				sprintf(
277
+					esc_html__(
278
+						'"%1$s" is not a valid loader method on EE_Registry.',
279
+						'event_espresso'
280
+					),
281
+					$loader
282
+				)
283
+			);
284
+		}
285
+		$class_name = EE_Dependency_Map::$_instance->getFqnForAlias($class_name);
286
+		if (! isset(EE_Dependency_Map::$_instance->_class_loaders[ $class_name ])) {
287
+			EE_Dependency_Map::$_instance->_class_loaders[ $class_name ] = $loader;
288
+			return true;
289
+		}
290
+		return false;
291
+	}
292
+
293
+
294
+	/**
295
+	 * @return array
296
+	 */
297
+	public function dependency_map()
298
+	{
299
+		return $this->_dependency_map;
300
+	}
301
+
302
+
303
+	/**
304
+	 * returns TRUE if dependency map contains a listing for the provided class name
305
+	 *
306
+	 * @param string $class_name
307
+	 * @return boolean
308
+	 */
309
+	public function has($class_name = '')
310
+	{
311
+		// all legacy models have the same dependencies
312
+		if (strpos($class_name, 'EEM_') === 0) {
313
+			$class_name = 'LEGACY_MODELS';
314
+		}
315
+		return isset($this->_dependency_map[ $class_name ]);
316
+	}
317
+
318
+
319
+	/**
320
+	 * returns TRUE if dependency map contains a listing for the provided class name AND dependency
321
+	 *
322
+	 * @param string $class_name
323
+	 * @param string $dependency
324
+	 * @return bool
325
+	 */
326
+	public function has_dependency_for_class($class_name = '', $dependency = '')
327
+	{
328
+		// all legacy models have the same dependencies
329
+		if (strpos($class_name, 'EEM_') === 0) {
330
+			$class_name = 'LEGACY_MODELS';
331
+		}
332
+		$dependency = $this->getFqnForAlias($dependency, $class_name);
333
+		return isset($this->_dependency_map[ $class_name ][ $dependency ]);
334
+	}
335
+
336
+
337
+	/**
338
+	 * returns loading strategy for whether a previously cached dependency should be loaded or a new instance returned
339
+	 *
340
+	 * @param string $class_name
341
+	 * @param string $dependency
342
+	 * @return int
343
+	 */
344
+	public function loading_strategy_for_class_dependency($class_name = '', $dependency = '')
345
+	{
346
+		// all legacy models have the same dependencies
347
+		if (strpos($class_name, 'EEM_') === 0) {
348
+			$class_name = 'LEGACY_MODELS';
349
+		}
350
+		$dependency = $this->getFqnForAlias($dependency);
351
+		return $this->has_dependency_for_class($class_name, $dependency)
352
+			? $this->_dependency_map[ $class_name ][ $dependency ]
353
+			: EE_Dependency_Map::not_registered;
354
+	}
355
+
356
+
357
+	/**
358
+	 * @param string $class_name
359
+	 * @return string | Closure
360
+	 */
361
+	public function class_loader($class_name)
362
+	{
363
+		// all legacy models use load_model()
364
+		if (strpos($class_name, 'EEM_') === 0) {
365
+			return 'load_model';
366
+		}
367
+		// EE_CPT_*_Strategy classes like EE_CPT_Event_Strategy, EE_CPT_Venue_Strategy, etc
368
+		// perform strpos() first to avoid loading regex every time we load a class
369
+		if (strpos($class_name, 'EE_CPT_') === 0
370
+			&& preg_match('/^EE_CPT_([a-zA-Z]+)_Strategy$/', $class_name)
371
+		) {
372
+			return 'load_core';
373
+		}
374
+		$class_name = $this->getFqnForAlias($class_name);
375
+		return isset($this->_class_loaders[ $class_name ]) ? $this->_class_loaders[ $class_name ] : '';
376
+	}
377
+
378
+
379
+	/**
380
+	 * @return array
381
+	 */
382
+	public function class_loaders()
383
+	{
384
+		return $this->_class_loaders;
385
+	}
386
+
387
+
388
+	/**
389
+	 * adds an alias for a classname
390
+	 *
391
+	 * @param string $fqcn      the class name that should be used (concrete class to replace interface)
392
+	 * @param string $alias     the class name that would be type hinted for (abstract parent or interface)
393
+	 * @param string $for_class the class that has the dependency (is type hinting for the interface)
394
+	 * @throws InvalidAliasException
395
+	 */
396
+	public function add_alias($fqcn, $alias, $for_class = '')
397
+	{
398
+		$this->class_cache->addAlias($fqcn, $alias, $for_class);
399
+	}
400
+
401
+
402
+	/**
403
+	 * Returns TRUE if the provided fully qualified name IS an alias
404
+	 * WHY?
405
+	 * Because if a class is type hinting for a concretion,
406
+	 * then why would we need to find another class to supply it?
407
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
408
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
409
+	 * Don't go looking for some substitute.
410
+	 * Whereas if a class is type hinting for an interface...
411
+	 * then we need to find an actual class to use.
412
+	 * So the interface IS the alias for some other FQN,
413
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
414
+	 * represents some other class.
415
+	 *
416
+	 * @param string $fqn
417
+	 * @param string $for_class
418
+	 * @return bool
419
+	 */
420
+	public function isAlias($fqn = '', $for_class = '')
421
+	{
422
+		return $this->class_cache->isAlias($fqn, $for_class);
423
+	}
424
+
425
+
426
+	/**
427
+	 * Returns a FQN for provided alias if one exists, otherwise returns the original $alias
428
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
429
+	 *  for example:
430
+	 *      if the following two entries were added to the _aliases array:
431
+	 *          array(
432
+	 *              'interface_alias'           => 'some\namespace\interface'
433
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
434
+	 *          )
435
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
436
+	 *      to load an instance of 'some\namespace\classname'
437
+	 *
438
+	 * @param string $alias
439
+	 * @param string $for_class
440
+	 * @return string
441
+	 */
442
+	public function getFqnForAlias($alias = '', $for_class = '')
443
+	{
444
+		return (string) $this->class_cache->getFqnForAlias($alias, $for_class);
445
+	}
446
+
447
+
448
+	/**
449
+	 * Registers the core dependencies and whether a previously instantiated object should be loaded from the cache,
450
+	 * if one exists, or whether a new object should be generated every time the requested class is loaded.
451
+	 * This is done by using the following class constants:
452
+	 *        EE_Dependency_Map::load_from_cache - loads previously instantiated object
453
+	 *        EE_Dependency_Map::load_new_object - generates a new object every time
454
+	 */
455
+	protected function _register_core_dependencies()
456
+	{
457
+		$this->_dependency_map = [
458
+			'EE_Request_Handler'                                                                                          => [
459
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
460
+			],
461
+			'EE_System'                                                                                                   => [
462
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
463
+				'EE_Maintenance_Mode'                         => EE_Dependency_Map::load_from_cache,
464
+				'EE_Registry'                                 => EE_Dependency_Map::load_from_cache,
465
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
466
+				'EventEspresso\core\services\routing\Router'  => EE_Dependency_Map::load_from_cache,
467
+			],
468
+			'EE_Admin'                                                                                                    => [
469
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
470
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
471
+			],
472
+			'EE_Cart'                                                                                                     => [
473
+				'EE_Session' => EE_Dependency_Map::load_from_cache,
474
+			],
475
+			'EE_Messenger_Collection_Loader'                                                                              => [
476
+				'EE_Messenger_Collection' => EE_Dependency_Map::load_new_object,
477
+			],
478
+			'EE_Message_Type_Collection_Loader'                                                                           => [
479
+				'EE_Message_Type_Collection' => EE_Dependency_Map::load_new_object,
480
+			],
481
+			'EE_Message_Resource_Manager'                                                                                 => [
482
+				'EE_Messenger_Collection_Loader'    => EE_Dependency_Map::load_new_object,
483
+				'EE_Message_Type_Collection_Loader' => EE_Dependency_Map::load_new_object,
484
+				'EEM_Message_Template_Group'        => EE_Dependency_Map::load_from_cache,
485
+			],
486
+			'EE_Message_Factory'                                                                                          => [
487
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
488
+			],
489
+			'EE_messages'                                                                                                 => [
490
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
491
+			],
492
+			'EE_Messages_Generator'                                                                                       => [
493
+				'EE_Messages_Queue'                    => EE_Dependency_Map::load_new_object,
494
+				'EE_Messages_Data_Handler_Collection'  => EE_Dependency_Map::load_new_object,
495
+				'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object,
496
+				'EEH_Parse_Shortcodes'                 => EE_Dependency_Map::load_from_cache,
497
+			],
498
+			'EE_Messages_Processor'                                                                                       => [
499
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
500
+			],
501
+			'EE_Messages_Queue'                                                                                           => [
502
+				'EE_Message_Repository' => EE_Dependency_Map::load_new_object,
503
+			],
504
+			'EE_Messages_Template_Defaults'                                                                               => [
505
+				'EEM_Message_Template_Group' => EE_Dependency_Map::load_from_cache,
506
+				'EEM_Message_Template'       => EE_Dependency_Map::load_from_cache,
507
+			],
508
+			'EE_Message_To_Generate_From_Request'                                                                         => [
509
+				'EE_Message_Resource_Manager' => EE_Dependency_Map::load_from_cache,
510
+				'EE_Request_Handler'          => EE_Dependency_Map::load_from_cache,
511
+			],
512
+			'EventEspresso\core\services\commands\CommandBus'                                                             => [
513
+				'EventEspresso\core\services\commands\CommandHandlerManager' => EE_Dependency_Map::load_from_cache,
514
+			],
515
+			'EventEspresso\services\commands\CommandHandler'                                                              => [
516
+				'EE_Registry'         => EE_Dependency_Map::load_from_cache,
517
+				'CommandBusInterface' => EE_Dependency_Map::load_from_cache,
518
+			],
519
+			'EventEspresso\core\services\commands\CommandHandlerManager'                                                  => [
520
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
521
+			],
522
+			'EventEspresso\core\services\commands\CompositeCommandHandler'                                                => [
523
+				'EventEspresso\core\services\commands\CommandBus'     => EE_Dependency_Map::load_from_cache,
524
+				'EventEspresso\core\services\commands\CommandFactory' => EE_Dependency_Map::load_from_cache,
525
+			],
526
+			'EventEspresso\core\services\commands\CommandFactory'                                                         => [
527
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
528
+			],
529
+			'EventEspresso\core\services\commands\middleware\CapChecker'                                                  => [
530
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
531
+			],
532
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker'                                         => [
533
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
534
+			],
535
+			'EventEspresso\core\domain\services\capabilities\RegistrationsCapChecker'                                     => [
536
+				'EE_Capabilities' => EE_Dependency_Map::load_from_cache,
537
+			],
538
+			'EventEspresso\core\services\commands\registration\CreateRegistrationCommandHandler'                          => [
539
+				'EventEspresso\core\domain\services\registration\CreateRegistrationService' => EE_Dependency_Map::load_from_cache,
540
+			],
541
+			'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommandHandler'                     => [
542
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
543
+			],
544
+			'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommandHandler'                    => [
545
+				'EventEspresso\core\domain\services\registration\CopyRegistrationService' => EE_Dependency_Map::load_from_cache,
546
+			],
547
+			'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler'         => [
548
+				'EventEspresso\core\domain\services\registration\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
549
+			],
550
+			'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler' => [
551
+				'EventEspresso\core\domain\services\registration\UpdateRegistrationService' => EE_Dependency_Map::load_from_cache,
552
+			],
553
+			'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommandHandler'                              => [
554
+				'EventEspresso\core\domain\services\ticket\CreateTicketLineItemService' => EE_Dependency_Map::load_from_cache,
555
+			],
556
+			'EventEspresso\core\services\commands\ticket\CancelTicketLineItemCommandHandler'                              => [
557
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
558
+			],
559
+			'EventEspresso\core\domain\services\registration\CancelRegistrationService'                                   => [
560
+				'EventEspresso\core\domain\services\ticket\CancelTicketLineItemService' => EE_Dependency_Map::load_from_cache,
561
+			],
562
+			'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler'                                  => [
563
+				'EEM_Attendee' => EE_Dependency_Map::load_from_cache,
564
+			],
565
+			'EventEspresso\core\services\database\TableManager'                                                           => [
566
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
567
+			],
568
+			'EE_Data_Migration_Class_Base'                                                                                => [
569
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
570
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
571
+			],
572
+			'EE_DMS_Core_4_1_0'                                                                                           => [
573
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
574
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
575
+			],
576
+			'EE_DMS_Core_4_2_0'                                                                                           => [
577
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
578
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
579
+			],
580
+			'EE_DMS_Core_4_3_0'                                                                                           => [
581
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
582
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
583
+			],
584
+			'EE_DMS_Core_4_4_0'                                                                                           => [
585
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
586
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
587
+			],
588
+			'EE_DMS_Core_4_5_0'                                                                                           => [
589
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
590
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
591
+			],
592
+			'EE_DMS_Core_4_6_0'                                                                                           => [
593
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
594
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
595
+			],
596
+			'EE_DMS_Core_4_7_0'                                                                                           => [
597
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
598
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
599
+			],
600
+			'EE_DMS_Core_4_8_0'                                                                                           => [
601
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
602
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
603
+			],
604
+			'EE_DMS_Core_4_9_0'                                                                                           => [
605
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
606
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
607
+			],
608
+			'EE_DMS_Core_4_10_0'                                                                                          => [
609
+				'EventEspresso\core\services\database\TableAnalysis' => EE_Dependency_Map::load_from_cache,
610
+				'EventEspresso\core\services\database\TableManager'  => EE_Dependency_Map::load_from_cache,
611
+				'EE_DMS_Core_4_9_0'                                  => EE_Dependency_Map::load_from_cache,
612
+			],
613
+			'EventEspresso\core\services\assets\I18nRegistry'                                                             => [
614
+				'EventEspresso\core\domain\Domain'                 => EE_Dependency_Map::load_from_cache,
615
+				'EventEspresso\core\services\assets\JedLocaleData' => EE_Dependency_Map::load_from_cache,
616
+				[],
617
+			],
618
+			'EventEspresso\core\services\assets\Registry'                                                                 => [
619
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
620
+				'EventEspresso\core\services\assets\I18nRegistry'    => EE_Dependency_Map::load_from_cache,
621
+			],
622
+			'EventEspresso\core\services\cache\BasicCacheManager'                                                         => [
623
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
624
+			],
625
+			'EventEspresso\core\services\cache\PostRelatedCacheManager'                                                   => [
626
+				'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache,
627
+			],
628
+			'EventEspresso\core\domain\services\validation\email\EmailValidationService'                                  => [
629
+				'EE_Registration_Config'                     => EE_Dependency_Map::load_from_cache,
630
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
631
+			],
632
+			'EventEspresso\core\domain\values\EmailAddress'                                                               => [
633
+				null,
634
+				'EventEspresso\core\domain\services\validation\email\EmailValidationService' => EE_Dependency_Map::load_from_cache,
635
+			],
636
+			'EventEspresso\core\services\orm\ModelFieldFactory'                                                           => [
637
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
638
+			],
639
+			'LEGACY_MODELS'                                                                                               => [
640
+				null,
641
+				'EventEspresso\core\services\database\ModelFieldFactory' => EE_Dependency_Map::load_from_cache,
642
+			],
643
+			'EE_Module_Request_Router'                                                                                    => [
644
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
645
+			],
646
+			'EE_Registration_Processor'                                                                                   => [
647
+				'EE_Request' => EE_Dependency_Map::load_from_cache,
648
+			],
649
+			'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'                                      => [
650
+				null,
651
+				'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker' => EE_Dependency_Map::load_from_cache,
652
+				'EventEspresso\core\services\request\Request'                         => EE_Dependency_Map::load_from_cache,
653
+			],
654
+			'EventEspresso\caffeinated\modules\recaptcha_invisible\InvisibleRecaptcha'                                    => [
655
+				'EE_Registration_Config' => EE_Dependency_Map::load_from_cache,
656
+				'EE_Session'             => EE_Dependency_Map::load_from_cache,
657
+			],
658
+			'EventEspresso\modules\ticket_selector\ProcessTicketSelector'                                                 => [
659
+				'EE_Core_Config'                                                          => EE_Dependency_Map::load_from_cache,
660
+				'EventEspresso\core\services\request\Request'                             => EE_Dependency_Map::load_from_cache,
661
+				'EE_Session'                                                              => EE_Dependency_Map::load_from_cache,
662
+				'EEM_Ticket'                                                              => EE_Dependency_Map::load_from_cache,
663
+				'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker' => EE_Dependency_Map::load_from_cache,
664
+			],
665
+			'EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker'                                     => [
666
+				'EEM_Datetime' => EE_Dependency_Map::load_from_cache,
667
+			],
668
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'                              => [
669
+				'EE_Core_Config'                             => EE_Dependency_Map::load_from_cache,
670
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
671
+			],
672
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'                                => [
673
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
674
+			],
675
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'                               => [
676
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
677
+			],
678
+			'EE_CPT_Strategy'                                                                                             => [
679
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache,
680
+				'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache,
681
+			],
682
+			'EventEspresso\core\services\loaders\ObjectIdentifier'                                                        => [
683
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
684
+			],
685
+			'EventEspresso\core\CPTs\CptQueryModifier'                                                                    => [
686
+				null,
687
+				null,
688
+				null,
689
+				'EE_Request_Handler'                          => EE_Dependency_Map::load_from_cache,
690
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
691
+				'EventEspresso\core\services\loaders\Loader'  => EE_Dependency_Map::load_from_cache,
692
+			],
693
+			'EventEspresso\core\services\dependencies\DependencyResolver'                                                 => [
694
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
695
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
696
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
697
+			],
698
+			'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver'                               => [
699
+				'EventEspresso\core\services\container\Mirror'            => EE_Dependency_Map::load_from_cache,
700
+				'EventEspresso\core\services\loaders\ClassInterfaceCache' => EE_Dependency_Map::load_from_cache,
701
+				'EE_Dependency_Map'                                       => EE_Dependency_Map::load_from_cache,
702
+			],
703
+			'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'                                          => [
704
+				'EventEspresso\core\services\routing\RouteMatchSpecificationDependencyResolver' => EE_Dependency_Map::load_from_cache,
705
+				'EventEspresso\core\services\loaders\Loader'                                    => EE_Dependency_Map::load_from_cache,
706
+			],
707
+			'EventEspresso\core\services\routing\RouteMatchSpecificationManager'                                          => [
708
+				'EventEspresso\core\services\routing\RouteMatchSpecificationCollection' => EE_Dependency_Map::load_from_cache,
709
+				'EventEspresso\core\services\routing\RouteMatchSpecificationFactory'    => EE_Dependency_Map::load_from_cache,
710
+			],
711
+			'EE_URL_Validation_Strategy'                                                                                  => [
712
+				null,
713
+				null,
714
+				'EventEspresso\core\services\validators\URLValidator' => EE_Dependency_Map::load_from_cache,
715
+			],
716
+			'EventEspresso\core\services\request\files\FilesDataHandler'                                                  => [
717
+				'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache,
718
+			],
719
+			'EventEspressoBatchRequest\BatchRequestProcessor'                                                             => [
720
+				'EventEspresso\core\services\loaders\Loader' => EE_Dependency_Map::load_from_cache,
721
+			],
722
+			'EventEspresso\core\domain\services\converters\RestApiSpoofer'                                                => [
723
+				'WP_REST_Server'                                               => EE_Dependency_Map::load_from_cache,
724
+				'EED_Core_Rest_Api'                                            => EE_Dependency_Map::load_from_cache,
725
+				'EventEspresso\core\libraries\rest_api\controllers\model\Read' => EE_Dependency_Map::load_from_cache,
726
+				null,
727
+			],
728
+			'EventEspresso\core\services\routing\RouteHandler'                                                            => [
729
+				'EventEspresso\core\services\json\JsonDataNodeHandler' => EE_Dependency_Map::load_from_cache,
730
+				'EventEspresso\core\services\loaders\Loader'           => EE_Dependency_Map::load_from_cache,
731
+				'EventEspresso\core\services\request\Request'          => EE_Dependency_Map::load_from_cache,
732
+				'EventEspresso\core\services\routing\RouteCollection'  => EE_Dependency_Map::load_from_cache,
733
+			],
734
+			'EventEspresso\core\services\json\JsonDataNodeHandler'                                                        => [
735
+				'EventEspresso\core\services\json\JsonDataNodeValidator' => EE_Dependency_Map::load_from_cache,
736
+			],
737
+			'EventEspresso\core\domain\services\assets\EspressoCoreAppAssetManager'                                       => [
738
+				'EventEspresso\core\domain\Domain'                   => EE_Dependency_Map::load_from_cache,
739
+				'EventEspresso\core\services\assets\AssetCollection' => EE_Dependency_Map::load_from_cache,
740
+				'EventEspresso\core\services\assets\Registry'        => EE_Dependency_Map::load_from_cache,
741
+			],
742
+			'EventEspresso\core\services\routing\Router'                                                                  => [
743
+				'EE_Dependency_Map'                                => EE_Dependency_Map::load_from_cache,
744
+				'EventEspresso\core\services\loaders\Loader'       => EE_Dependency_Map::load_from_cache,
745
+				'EventEspresso\core\services\routing\RouteHandler' => EE_Dependency_Map::load_from_cache,
746
+			],
747
+		];
748
+	}
749
+
750
+
751
+	/**
752
+	 * Registers how core classes are loaded.
753
+	 * This can either be done by simply providing the name of one of the EE_Registry loader methods such as:
754
+	 *        'EE_Request_Handler' => 'load_core'
755
+	 *        'EE_Messages_Queue'  => 'load_lib'
756
+	 *        'EEH_Debug_Tools'    => 'load_helper'
757
+	 * or, if greater control is required, by providing a custom closure. For example:
758
+	 *        'Some_Class' => function () {
759
+	 *            return new Some_Class();
760
+	 *        },
761
+	 * This is required for instantiating dependencies
762
+	 * where an interface has been type hinted in a class constructor. For example:
763
+	 *        'Required_Interface' => function () {
764
+	 *            return new A_Class_That_Implements_Required_Interface();
765
+	 *        },
766
+	 */
767
+	protected function _register_core_class_loaders()
768
+	{
769
+		$this->_class_loaders = [
770
+			// load_core
771
+			'EE_Dependency_Map'                            => function () {
772
+				return $this;
773
+			},
774
+			'EE_Capabilities'                              => 'load_core',
775
+			'EE_Encryption'                                => 'load_core',
776
+			'EE_Front_Controller'                          => 'load_core',
777
+			'EE_Module_Request_Router'                     => 'load_core',
778
+			'EE_Registry'                                  => 'load_core',
779
+			'EE_Request'                                   => function () {
780
+				return $this->legacy_request;
781
+			},
782
+			'EventEspresso\core\services\request\Request'  => function () {
783
+				return $this->request;
784
+			},
785
+			'EventEspresso\core\services\request\Response' => function () {
786
+				return $this->response;
787
+			},
788
+			'EE_Base'                                      => 'load_core',
789
+			'EE_Request_Handler'                           => 'load_core',
790
+			'EE_Session'                                   => 'load_core',
791
+			'EE_Cron_Tasks'                                => 'load_core',
792
+			'EE_System'                                    => 'load_core',
793
+			'EE_Maintenance_Mode'                          => 'load_core',
794
+			'EE_Register_CPTs'                             => 'load_core',
795
+			'EE_Admin'                                     => 'load_core',
796
+			'EE_CPT_Strategy'                              => 'load_core',
797
+			// load_class
798
+			'EE_Registration_Processor'                    => 'load_class',
799
+			// load_lib
800
+			'EE_Message_Resource_Manager'                  => 'load_lib',
801
+			'EE_Message_Type_Collection'                   => 'load_lib',
802
+			'EE_Message_Type_Collection_Loader'            => 'load_lib',
803
+			'EE_Messenger_Collection'                      => 'load_lib',
804
+			'EE_Messenger_Collection_Loader'               => 'load_lib',
805
+			'EE_Messages_Processor'                        => 'load_lib',
806
+			'EE_Message_Repository'                        => 'load_lib',
807
+			'EE_Messages_Queue'                            => 'load_lib',
808
+			'EE_Messages_Data_Handler_Collection'          => 'load_lib',
809
+			'EE_Message_Template_Group_Collection'         => 'load_lib',
810
+			'EE_Payment_Method_Manager'                    => 'load_lib',
811
+			'EE_DMS_Core_4_1_0'                            => 'load_dms',
812
+			'EE_DMS_Core_4_2_0'                            => 'load_dms',
813
+			'EE_DMS_Core_4_3_0'                            => 'load_dms',
814
+			'EE_DMS_Core_4_5_0'                            => 'load_dms',
815
+			'EE_DMS_Core_4_6_0'                            => 'load_dms',
816
+			'EE_DMS_Core_4_7_0'                            => 'load_dms',
817
+			'EE_DMS_Core_4_8_0'                            => 'load_dms',
818
+			'EE_DMS_Core_4_9_0'                            => 'load_dms',
819
+			'EE_DMS_Core_4_10_0'                           => 'load_dms',
820
+			'EE_Messages_Generator'                        => static function () {
821
+				return EE_Registry::instance()->load_lib(
822
+					'Messages_Generator',
823
+					[],
824
+					false,
825
+					false
826
+				);
827
+			},
828
+			'EE_Messages_Template_Defaults'                => static function ($arguments = []) {
829
+				return EE_Registry::instance()->load_lib(
830
+					'Messages_Template_Defaults',
831
+					$arguments,
832
+					false,
833
+					false
834
+				);
835
+			},
836
+			// load_helper
837
+			'EEH_Parse_Shortcodes'                         => static function () {
838
+				if (EE_Registry::instance()->load_helper('Parse_Shortcodes')) {
839
+					return new EEH_Parse_Shortcodes();
840
+				}
841
+				return null;
842
+			},
843
+			'EE_Template_Config'                           => static function () {
844
+				return EE_Config::instance()->template_settings;
845
+			},
846
+			'EE_Currency_Config'                           => static function () {
847
+				return EE_Config::instance()->currency;
848
+			},
849
+			'EE_Registration_Config'                       => static function () {
850
+				return EE_Config::instance()->registration;
851
+			},
852
+			'EE_Core_Config'                               => static function () {
853
+				return EE_Config::instance()->core;
854
+			},
855
+			'EventEspresso\core\services\loaders\Loader'   => static function () {
856
+				return LoaderFactory::getLoader();
857
+			},
858
+			'EE_Network_Config'                            => static function () {
859
+				return EE_Network_Config::instance();
860
+			},
861
+			'EE_Config'                                    => static function () {
862
+				return EE_Config::instance();
863
+			},
864
+			'EventEspresso\core\domain\Domain'             => static function () {
865
+				return DomainFactory::getEventEspressoCoreDomain();
866
+			},
867
+			'EE_Admin_Config'                              => static function () {
868
+				return EE_Config::instance()->admin;
869
+			},
870
+			'EE_Organization_Config'                       => static function () {
871
+				return EE_Config::instance()->organization;
872
+			},
873
+			'EE_Network_Core_Config'                       => static function () {
874
+				return EE_Network_Config::instance()->core;
875
+			},
876
+			'EE_Environment_Config'                        => static function () {
877
+				return EE_Config::instance()->environment;
878
+			},
879
+			'EED_Core_Rest_Api'                            => static function () {
880
+				return EED_Core_Rest_Api::instance();
881
+			},
882
+			'WP_REST_Server'                               => static function () {
883
+				return rest_get_server();
884
+			},
885
+		];
886
+	}
887
+
888
+
889
+	/**
890
+	 * can be used for supplying alternate names for classes,
891
+	 * or for connecting interface names to instantiable classes
892
+	 *
893
+	 * @throws InvalidAliasException
894
+	 */
895
+	protected function _register_core_aliases()
896
+	{
897
+		$aliases = [
898
+			'CommandBusInterface'                                                          => 'EventEspresso\core\services\commands\CommandBusInterface',
899
+			'EventEspresso\core\services\commands\CommandBusInterface'                     => 'EventEspresso\core\services\commands\CommandBus',
900
+			'CommandHandlerManagerInterface'                                               => 'EventEspresso\core\services\commands\CommandHandlerManagerInterface',
901
+			'EventEspresso\core\services\commands\CommandHandlerManagerInterface'          => 'EventEspresso\core\services\commands\CommandHandlerManager',
902
+			'CapChecker'                                                                   => 'EventEspresso\core\services\commands\middleware\CapChecker',
903
+			'AddActionHook'                                                                => 'EventEspresso\core\services\commands\middleware\AddActionHook',
904
+			'CapabilitiesChecker'                                                          => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
905
+			'CapabilitiesCheckerInterface'                                                 => 'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface',
906
+			'EventEspresso\core\domain\services\capabilities\CapabilitiesCheckerInterface' => 'EventEspresso\core\domain\services\capabilities\CapabilitiesChecker',
907
+			'CreateRegistrationService'                                                    => 'EventEspresso\core\domain\services\registration\CreateRegistrationService',
908
+			'CreateRegistrationCommandHandler'                                             => 'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
909
+			'CopyRegistrationDetailsCommandHandler'                                        => 'EventEspresso\core\services\commands\registration\CopyRegistrationDetailsCommand',
910
+			'CopyRegistrationPaymentsCommandHandler'                                       => 'EventEspresso\core\services\commands\registration\CopyRegistrationPaymentsCommand',
911
+			'CancelRegistrationAndTicketLineItemCommandHandler'                            => 'EventEspresso\core\services\commands\registration\CancelRegistrationAndTicketLineItemCommandHandler',
912
+			'UpdateRegistrationAndTransactionAfterChangeCommandHandler'                    => 'EventEspresso\core\services\commands\registration\UpdateRegistrationAndTransactionAfterChangeCommandHandler',
913
+			'CreateTicketLineItemCommandHandler'                                           => 'EventEspresso\core\services\commands\ticket\CreateTicketLineItemCommand',
914
+			'CreateTransactionCommandHandler'                                              => 'EventEspresso\core\services\commands\transaction\CreateTransactionCommandHandler',
915
+			'CreateAttendeeCommandHandler'                                                 => 'EventEspresso\core\services\commands\attendee\CreateAttendeeCommandHandler',
916
+			'TableManager'                                                                 => 'EventEspresso\core\services\database\TableManager',
917
+			'TableAnalysis'                                                                => 'EventEspresso\core\services\database\TableAnalysis',
918
+			'EspressoShortcode'                                                            => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
919
+			'ShortcodeInterface'                                                           => 'EventEspresso\core\services\shortcodes\ShortcodeInterface',
920
+			'EventEspresso\core\services\shortcodes\ShortcodeInterface'                    => 'EventEspresso\core\services\shortcodes\EspressoShortcode',
921
+			'EventEspresso\core\services\cache\CacheStorageInterface'                      => 'EventEspresso\core\services\cache\TransientCacheStorage',
922
+			'LoaderInterface'                                                              => 'EventEspresso\core\services\loaders\LoaderInterface',
923
+			'EventEspresso\core\services\loaders\LoaderInterface'                          => 'EventEspresso\core\services\loaders\Loader',
924
+			'CommandFactoryInterface'                                                      => 'EventEspresso\core\services\commands\CommandFactoryInterface',
925
+			'EventEspresso\core\services\commands\CommandFactoryInterface'                 => 'EventEspresso\core\services\commands\CommandFactory',
926
+			'EmailValidatorInterface'                                                      => 'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface',
927
+			'EventEspresso\core\domain\services\validation\email\EmailValidatorInterface'  => 'EventEspresso\core\domain\services\validation\email\EmailValidationService',
928
+			'NoticeConverterInterface'                                                     => 'EventEspresso\core\services\notices\NoticeConverterInterface',
929
+			'EventEspresso\core\services\notices\NoticeConverterInterface'                 => 'EventEspresso\core\services\notices\ConvertNoticesToEeErrors',
930
+			'NoticesContainerInterface'                                                    => 'EventEspresso\core\services\notices\NoticesContainerInterface',
931
+			'EventEspresso\core\services\notices\NoticesContainerInterface'                => 'EventEspresso\core\services\notices\NoticesContainer',
932
+			'EventEspresso\core\services\request\RequestInterface'                         => 'EventEspresso\core\services\request\Request',
933
+			'EventEspresso\core\services\request\ResponseInterface'                        => 'EventEspresso\core\services\request\Response',
934
+			'EventEspresso\core\domain\DomainInterface'                                    => 'EventEspresso\core\domain\Domain',
935
+			'Registration_Processor'                                                       => 'EE_Registration_Processor',
936
+		];
937
+		foreach ($aliases as $alias => $fqn) {
938
+			if (is_array($fqn)) {
939
+				foreach ($fqn as $class => $for_class) {
940
+					$this->class_cache->addAlias($class, $alias, $for_class);
941
+				}
942
+				continue;
943
+			}
944
+			$this->class_cache->addAlias($fqn, $alias);
945
+		}
946
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
947
+			$this->class_cache->addAlias(
948
+				'EventEspresso\core\services\notices\ConvertNoticesToAdminNotices',
949
+				'EventEspresso\core\services\notices\NoticeConverterInterface'
950
+			);
951
+		}
952
+	}
953
+
954
+
955
+	/**
956
+	 * This is used to reset the internal map and class_loaders to their original default state at the beginning of the
957
+	 * request Primarily used by unit tests.
958
+	 */
959
+	public function reset()
960
+	{
961
+		$this->_register_core_class_loaders();
962
+		$this->_register_core_dependencies();
963
+	}
964
+
965
+
966
+	/**
967
+	 * PLZ NOTE: a better name for this method would be is_alias()
968
+	 * because it returns TRUE if the provided fully qualified name IS an alias
969
+	 * WHY?
970
+	 * Because if a class is type hinting for a concretion,
971
+	 * then why would we need to find another class to supply it?
972
+	 * ie: if a class asks for `Fully/Qualified/Namespace/SpecificClassName`,
973
+	 * then give it an instance of `Fully/Qualified/Namespace/SpecificClassName`.
974
+	 * Don't go looking for some substitute.
975
+	 * Whereas if a class is type hinting for an interface...
976
+	 * then we need to find an actual class to use.
977
+	 * So the interface IS the alias for some other FQN,
978
+	 * and we need to find out if `Fully/Qualified/Namespace/SomeInterface`
979
+	 * represents some other class.
980
+	 *
981
+	 * @param string $fqn
982
+	 * @param string $for_class
983
+	 * @return bool
984
+	 * @deprecated 4.9.62.p
985
+	 */
986
+	public function has_alias($fqn = '', $for_class = '')
987
+	{
988
+		return $this->isAlias($fqn, $for_class);
989
+	}
990
+
991
+
992
+	/**
993
+	 * PLZ NOTE: a better name for this method would be get_fqn_for_alias()
994
+	 * because it returns a FQN for provided alias if one exists, otherwise returns the original $alias
995
+	 * functions recursively, so that multiple aliases can be used to drill down to a FQN
996
+	 *  for example:
997
+	 *      if the following two entries were added to the _aliases array:
998
+	 *          array(
999
+	 *              'interface_alias'           => 'some\namespace\interface'
1000
+	 *              'some\namespace\interface'  => 'some\namespace\classname'
1001
+	 *          )
1002
+	 *      then one could use EE_Registry::instance()->create( 'interface_alias' )
1003
+	 *      to load an instance of 'some\namespace\classname'
1004
+	 *
1005
+	 * @param string $alias
1006
+	 * @param string $for_class
1007
+	 * @return string
1008
+	 * @deprecated 4.9.62.p
1009
+	 */
1010
+	public function get_alias($alias = '', $for_class = '')
1011
+	{
1012
+		return $this->getFqnForAlias($alias, $for_class);
1013
+	}
1014 1014
 }
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1690 added lines, -1690 removed lines patch added patch discarded remove patch
@@ -23,1694 +23,1694 @@
 block discarded – undo
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registry $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var EE_Dependency_Map $_dependency_map
33
-     */
34
-    protected $_dependency_map;
35
-
36
-    /**
37
-     * @var Mirror
38
-     */
39
-    private $mirror;
40
-
41
-    /**
42
-     * @var ClassInterfaceCache $class_cache
43
-     */
44
-    private $class_cache;
45
-
46
-    /**
47
-     * @var array $_class_abbreviations
48
-     */
49
-    protected $_class_abbreviations = array();
50
-
51
-    /**
52
-     * @var CommandBusInterface $BUS
53
-     */
54
-    public $BUS;
55
-
56
-    /**
57
-     * @var EE_Cart $CART
58
-     */
59
-    public $CART;
60
-
61
-    /**
62
-     * @var EE_Config $CFG
63
-     */
64
-    public $CFG;
65
-
66
-    /**
67
-     * @var EE_Network_Config $NET_CFG
68
-     */
69
-    public $NET_CFG;
70
-
71
-    /**
72
-     * StdClass object for storing library classes in
73
-     *
74
-     * @var RegistryContainer $LIB
75
-     */
76
-    public $LIB;
77
-
78
-    /**
79
-     * @var EE_Request_Handler $REQ
80
-     */
81
-    public $REQ;
82
-
83
-    /**
84
-     * @var EE_Session $SSN
85
-     */
86
-    public $SSN;
87
-
88
-    /**
89
-     * @since 4.5.0
90
-     * @var EE_Capabilities $CAP
91
-     */
92
-    public $CAP;
93
-
94
-    /**
95
-     * @since 4.9.0
96
-     * @var EE_Message_Resource_Manager $MRM
97
-     */
98
-    public $MRM;
99
-
100
-    /**
101
-     * @var Registry $AssetsRegistry
102
-     */
103
-    public $AssetsRegistry;
104
-
105
-    /**
106
-     * StdClass object for holding addons which have registered themselves to work with EE core
107
-     *
108
-     * @var EE_Addon[] $addons
109
-     */
110
-    public $addons;
111
-
112
-    /**
113
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
-     *
115
-     * @var EEM_Base[] $models
116
-     */
117
-    public $models = array();
118
-
119
-    /**
120
-     * @var EED_Module[] $modules
121
-     */
122
-    public $modules;
123
-
124
-    /**
125
-     * @var EES_Shortcode[] $shortcodes
126
-     */
127
-    public $shortcodes;
128
-
129
-    /**
130
-     * @var WP_Widget[] $widgets
131
-     */
132
-    public $widgets;
133
-
134
-    /**
135
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
-     * classnames (eg "EEM_Event")
139
-     *
140
-     * @var array $non_abstract_db_models
141
-     */
142
-    public $non_abstract_db_models = array();
143
-
144
-    /**
145
-     * internationalization for JS strings
146
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
-     *    in js file:  var translatedString = eei18n.string_key;
148
-     *
149
-     * @var array $i18n_js_strings
150
-     */
151
-    public static $i18n_js_strings = array();
152
-
153
-    /**
154
-     * $main_file - path to espresso.php
155
-     *
156
-     * @var array $main_file
157
-     */
158
-    public $main_file;
159
-
160
-    /**
161
-     * array of ReflectionClass objects where the key is the class name
162
-     *
163
-     * @deprecated 4.9.62.p
164
-     * @var ReflectionClass[] $_reflectors
165
-     */
166
-    public $_reflectors;
167
-
168
-    /**
169
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
-     *
171
-     * @var boolean $_cache_on
172
-     */
173
-    protected $_cache_on = true;
174
-
175
-    /**
176
-     * @var ObjectIdentifier
177
-     */
178
-    private $object_identifier;
179
-
180
-
181
-    /**
182
-     * @singleton method used to instantiate class object
183
-     * @param EE_Dependency_Map|null   $dependency_map
184
-     * @param Mirror|null              $mirror
185
-     * @param ClassInterfaceCache|null $class_cache
186
-     * @param ObjectIdentifier|null    $object_identifier
187
-     * @return EE_Registry instance
188
-     */
189
-    public static function instance(
190
-        EE_Dependency_Map $dependency_map = null,
191
-        Mirror $mirror = null,
192
-        ClassInterfaceCache $class_cache = null,
193
-        ObjectIdentifier $object_identifier = null
194
-    ) {
195
-        // check if class object is instantiated
196
-        if (! self::$_instance instanceof EE_Registry
197
-            && $dependency_map instanceof EE_Dependency_Map
198
-            && $mirror instanceof Mirror
199
-            && $class_cache instanceof ClassInterfaceCache
200
-            && $object_identifier instanceof ObjectIdentifier
201
-        ) {
202
-            self::$_instance = new self(
203
-                $dependency_map,
204
-                $mirror,
205
-                $class_cache,
206
-                $object_identifier
207
-            );
208
-        }
209
-        return self::$_instance;
210
-    }
211
-
212
-
213
-    /**
214
-     * protected constructor to prevent direct creation
215
-     *
216
-     * @Constructor
217
-     * @param  EE_Dependency_Map  $dependency_map
218
-     * @param Mirror              $mirror
219
-     * @param ClassInterfaceCache $class_cache
220
-     * @param ObjectIdentifier    $object_identifier
221
-     */
222
-    protected function __construct(
223
-        EE_Dependency_Map $dependency_map,
224
-        Mirror $mirror,
225
-        ClassInterfaceCache $class_cache,
226
-        ObjectIdentifier $object_identifier
227
-    ) {
228
-        $this->_dependency_map = $dependency_map;
229
-        $this->mirror = $mirror;
230
-        $this->class_cache = $class_cache;
231
-        $this->object_identifier = $object_identifier;
232
-        // $registry_container = new RegistryContainer();
233
-        $this->LIB = new RegistryContainer();
234
-        $this->addons = new RegistryContainer();
235
-        $this->modules = new RegistryContainer();
236
-        $this->shortcodes = new RegistryContainer();
237
-        $this->widgets = new RegistryContainer();
238
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
239
-    }
240
-
241
-
242
-    /**
243
-     * initialize
244
-     *
245
-     * @throws OutOfBoundsException
246
-     * @throws InvalidArgumentException
247
-     * @throws InvalidInterfaceException
248
-     * @throws InvalidDataTypeException
249
-     * @throws EE_Error
250
-     * @throws ReflectionException
251
-     */
252
-    public function initialize()
253
-    {
254
-        $this->_class_abbreviations = apply_filters(
255
-            'FHEE__EE_Registry____construct___class_abbreviations',
256
-            array(
257
-                'EE_Config'                                       => 'CFG',
258
-                'EE_Session'                                      => 'SSN',
259
-                'EE_Capabilities'                                 => 'CAP',
260
-                'EE_Cart'                                         => 'CART',
261
-                'EE_Network_Config'                               => 'NET_CFG',
262
-                'EE_Request_Handler'                              => 'REQ',
263
-                'EE_Message_Resource_Manager'                     => 'MRM',
264
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
265
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
266
-            )
267
-        );
268
-        $this->load_core('Base', array(), true);
269
-        // add our request and response objects to the cache
270
-        $request_loader = $this->_dependency_map->class_loader(
271
-            'EventEspresso\core\services\request\Request'
272
-        );
273
-        $this->_set_cached_class(
274
-            $request_loader(),
275
-            'EventEspresso\core\services\request\Request'
276
-        );
277
-        $response_loader = $this->_dependency_map->class_loader(
278
-            'EventEspresso\core\services\request\Response'
279
-        );
280
-        $this->_set_cached_class(
281
-            $response_loader(),
282
-            'EventEspresso\core\services\request\Response'
283
-        );
284
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
285
-    }
286
-
287
-
288
-    /**
289
-     * @return void
290
-     */
291
-    public function init()
292
-    {
293
-        // Get current page protocol
294
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
295
-        // Output admin-ajax.php URL with same protocol as current page
296
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
297
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
298
-    }
299
-
300
-
301
-    /**
302
-     * localize_i18n_js_strings
303
-     *
304
-     * @return string
305
-     */
306
-    public static function localize_i18n_js_strings()
307
-    {
308
-        $i18n_js_strings = (array) self::$i18n_js_strings;
309
-        foreach ($i18n_js_strings as $key => $value) {
310
-            if (is_scalar($value)) {
311
-                $i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
-            }
313
-        }
314
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
315
-    }
316
-
317
-
318
-    /**
319
-     * @param mixed string | EED_Module $module
320
-     * @throws OutOfBoundsException
321
-     * @throws InvalidArgumentException
322
-     * @throws InvalidInterfaceException
323
-     * @throws InvalidDataTypeException
324
-     * @throws EE_Error
325
-     * @throws ReflectionException
326
-     */
327
-    public function add_module($module)
328
-    {
329
-        if ($module instanceof EED_Module) {
330
-            $module_class = get_class($module);
331
-            $this->modules->{$module_class} = $module;
332
-        } else {
333
-            if (! class_exists('EE_Module_Request_Router', false)) {
334
-                $this->load_core('Module_Request_Router');
335
-            }
336
-            EE_Module_Request_Router::module_factory($module);
337
-        }
338
-    }
339
-
340
-
341
-    /**
342
-     * @param string $module_name
343
-     * @return mixed EED_Module | NULL
344
-     */
345
-    public function get_module($module_name = '')
346
-    {
347
-        return isset($this->modules->{$module_name})
348
-            ? $this->modules->{$module_name}
349
-            : null;
350
-    }
351
-
352
-
353
-    /**
354
-     * loads core classes - must be singletons
355
-     *
356
-     * @param string $class_name - simple class name ie: session
357
-     * @param mixed  $arguments
358
-     * @param bool   $load_only
359
-     * @return mixed
360
-     * @throws InvalidInterfaceException
361
-     * @throws InvalidDataTypeException
362
-     * @throws EE_Error
363
-     * @throws ReflectionException
364
-     * @throws InvalidArgumentException
365
-     */
366
-    public function load_core($class_name, $arguments = array(), $load_only = false)
367
-    {
368
-        $core_paths = apply_filters(
369
-            'FHEE__EE_Registry__load_core__core_paths',
370
-            array(
371
-                EE_CORE,
372
-                EE_ADMIN,
373
-                EE_CPTS,
374
-                EE_CORE . 'data_migration_scripts/',
375
-                EE_CORE . 'capabilities/',
376
-                EE_CORE . 'request_stack/',
377
-                EE_CORE . 'middleware/',
378
-            )
379
-        );
380
-        // retrieve instantiated class
381
-        return $this->_load(
382
-            $core_paths,
383
-            'EE_',
384
-            $class_name,
385
-            'core',
386
-            $arguments,
387
-            false,
388
-            true,
389
-            $load_only
390
-        );
391
-    }
392
-
393
-
394
-    /**
395
-     * loads service classes
396
-     *
397
-     * @param string $class_name - simple class name ie: session
398
-     * @param mixed  $arguments
399
-     * @param bool   $load_only
400
-     * @return mixed
401
-     * @throws InvalidInterfaceException
402
-     * @throws InvalidDataTypeException
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     * @throws InvalidArgumentException
406
-     */
407
-    public function load_service($class_name, $arguments = array(), $load_only = false)
408
-    {
409
-        $service_paths = apply_filters(
410
-            'FHEE__EE_Registry__load_service__service_paths',
411
-            array(
412
-                EE_CORE . 'services/',
413
-            )
414
-        );
415
-        // retrieve instantiated class
416
-        return $this->_load(
417
-            $service_paths,
418
-            'EE_',
419
-            $class_name,
420
-            'class',
421
-            $arguments,
422
-            false,
423
-            true,
424
-            $load_only
425
-        );
426
-    }
427
-
428
-
429
-    /**
430
-     * loads data_migration_scripts
431
-     *
432
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
433
-     * @param mixed  $arguments
434
-     * @return EE_Data_Migration_Script_Base|mixed
435
-     * @throws InvalidInterfaceException
436
-     * @throws InvalidDataTypeException
437
-     * @throws EE_Error
438
-     * @throws ReflectionException
439
-     * @throws InvalidArgumentException
440
-     */
441
-    public function load_dms($class_name, $arguments = array())
442
-    {
443
-        // retrieve instantiated class
444
-        return $this->_load(
445
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
446
-            'EE_DMS_',
447
-            $class_name,
448
-            'dms',
449
-            $arguments,
450
-            false,
451
-            false
452
-        );
453
-    }
454
-
455
-
456
-    /**
457
-     * loads object creating classes - must be singletons
458
-     *
459
-     * @param string $class_name - simple class name ie: attendee
460
-     * @param mixed  $arguments  - an array of arguments to pass to the class
461
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
462
-     *                           instantiate
463
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
464
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
465
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
466
-     *                           (default)
467
-     * @return EE_Base_Class | bool
468
-     * @throws InvalidInterfaceException
469
-     * @throws InvalidDataTypeException
470
-     * @throws EE_Error
471
-     * @throws ReflectionException
472
-     * @throws InvalidArgumentException
473
-     */
474
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
475
-    {
476
-        $paths = apply_filters(
477
-            'FHEE__EE_Registry__load_class__paths',
478
-            array(
479
-                EE_CORE,
480
-                EE_CLASSES,
481
-                EE_BUSINESS,
482
-            )
483
-        );
484
-        // retrieve instantiated class
485
-        return $this->_load(
486
-            $paths,
487
-            'EE_',
488
-            $class_name,
489
-            'class',
490
-            $arguments,
491
-            $from_db,
492
-            $cache,
493
-            $load_only
494
-        );
495
-    }
496
-
497
-
498
-    /**
499
-     * loads helper classes - must be singletons
500
-     *
501
-     * @param string $class_name - simple class name ie: price
502
-     * @param mixed  $arguments
503
-     * @param bool   $load_only
504
-     * @return EEH_Base | bool
505
-     * @throws InvalidInterfaceException
506
-     * @throws InvalidDataTypeException
507
-     * @throws EE_Error
508
-     * @throws ReflectionException
509
-     * @throws InvalidArgumentException
510
-     */
511
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
512
-    {
513
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
514
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
515
-        // retrieve instantiated class
516
-        return $this->_load(
517
-            $helper_paths,
518
-            'EEH_',
519
-            $class_name,
520
-            'helper',
521
-            $arguments,
522
-            false,
523
-            true,
524
-            $load_only
525
-        );
526
-    }
527
-
528
-
529
-    /**
530
-     * loads core classes - must be singletons
531
-     *
532
-     * @param string $class_name - simple class name ie: session
533
-     * @param mixed  $arguments
534
-     * @param bool   $load_only
535
-     * @param bool   $cache      whether to cache the object or not.
536
-     * @return mixed
537
-     * @throws InvalidInterfaceException
538
-     * @throws InvalidDataTypeException
539
-     * @throws EE_Error
540
-     * @throws ReflectionException
541
-     * @throws InvalidArgumentException
542
-     */
543
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
544
-    {
545
-        $paths = array(
546
-            EE_LIBRARIES,
547
-            EE_LIBRARIES . 'messages/',
548
-            EE_LIBRARIES . 'shortcodes/',
549
-            EE_LIBRARIES . 'qtips/',
550
-            EE_LIBRARIES . 'payment_methods/',
551
-        );
552
-        // retrieve instantiated class
553
-        return $this->_load(
554
-            $paths,
555
-            'EE_',
556
-            $class_name,
557
-            'lib',
558
-            $arguments,
559
-            false,
560
-            $cache,
561
-            $load_only
562
-        );
563
-    }
564
-
565
-
566
-    /**
567
-     * loads model classes - must be singletons
568
-     *
569
-     * @param string $class_name - simple class name ie: price
570
-     * @param mixed  $arguments
571
-     * @param bool   $load_only
572
-     * @return EEM_Base | bool
573
-     * @throws InvalidInterfaceException
574
-     * @throws InvalidDataTypeException
575
-     * @throws EE_Error
576
-     * @throws ReflectionException
577
-     * @throws InvalidArgumentException
578
-     */
579
-    public function load_model($class_name, $arguments = array(), $load_only = false)
580
-    {
581
-        $paths = apply_filters(
582
-            'FHEE__EE_Registry__load_model__paths',
583
-            array(
584
-                EE_MODELS,
585
-                EE_CORE,
586
-            )
587
-        );
588
-        // retrieve instantiated class
589
-        return $this->_load(
590
-            $paths,
591
-            'EEM_',
592
-            $class_name,
593
-            'model',
594
-            $arguments,
595
-            false,
596
-            true,
597
-            $load_only
598
-        );
599
-    }
600
-
601
-
602
-    /**
603
-     * loads model classes - must be singletons
604
-     *
605
-     * @param string $class_name - simple class name ie: price
606
-     * @param mixed  $arguments
607
-     * @param bool   $load_only
608
-     * @return mixed | bool
609
-     * @throws InvalidInterfaceException
610
-     * @throws InvalidDataTypeException
611
-     * @throws EE_Error
612
-     * @throws ReflectionException
613
-     * @throws InvalidArgumentException
614
-     */
615
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
616
-    {
617
-        $paths = array(
618
-            EE_MODELS . 'fields/',
619
-            EE_MODELS . 'helpers/',
620
-            EE_MODELS . 'relations/',
621
-            EE_MODELS . 'strategies/',
622
-        );
623
-        // retrieve instantiated class
624
-        return $this->_load(
625
-            $paths,
626
-            'EE_',
627
-            $class_name,
628
-            '',
629
-            $arguments,
630
-            false,
631
-            true,
632
-            $load_only
633
-        );
634
-    }
635
-
636
-
637
-    /**
638
-     * Determines if $model_name is the name of an actual EE model.
639
-     *
640
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
641
-     * @return boolean
642
-     */
643
-    public function is_model_name($model_name)
644
-    {
645
-        return isset($this->models[ $model_name ]);
646
-    }
647
-
648
-
649
-    /**
650
-     * generic class loader
651
-     *
652
-     * @param string $path_to_file - directory path to file location, not including filename
653
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
654
-     * @param string $type         - file type - core? class? helper? model?
655
-     * @param mixed  $arguments
656
-     * @param bool   $load_only
657
-     * @return mixed
658
-     * @throws InvalidInterfaceException
659
-     * @throws InvalidDataTypeException
660
-     * @throws EE_Error
661
-     * @throws ReflectionException
662
-     * @throws InvalidArgumentException
663
-     */
664
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
665
-    {
666
-        // retrieve instantiated class
667
-        return $this->_load(
668
-            $path_to_file,
669
-            '',
670
-            $file_name,
671
-            $type,
672
-            $arguments,
673
-            false,
674
-            true,
675
-            $load_only
676
-        );
677
-    }
678
-
679
-
680
-    /**
681
-     * @param string $path_to_file - directory path to file location, not including filename
682
-     * @param string $class_name   - full class name  ie:  My_Class
683
-     * @param string $type         - file type - core? class? helper? model?
684
-     * @param mixed  $arguments
685
-     * @param bool   $load_only
686
-     * @return bool|EE_Addon|object
687
-     * @throws InvalidInterfaceException
688
-     * @throws InvalidDataTypeException
689
-     * @throws EE_Error
690
-     * @throws ReflectionException
691
-     * @throws InvalidArgumentException
692
-     */
693
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
694
-    {
695
-        // retrieve instantiated class
696
-        return $this->_load(
697
-            $path_to_file,
698
-            'addon',
699
-            $class_name,
700
-            $type,
701
-            $arguments,
702
-            false,
703
-            true,
704
-            $load_only
705
-        );
706
-    }
707
-
708
-
709
-    /**
710
-     * instantiates, caches, and automatically resolves dependencies
711
-     * for classes that use a Fully Qualified Class Name.
712
-     * if the class is not capable of being loaded using PSR-4 autoloading,
713
-     * then you need to use one of the existing load_*() methods
714
-     * which can resolve the classname and filepath from the passed arguments
715
-     *
716
-     * @param bool|string $class_name   Fully Qualified Class Name
717
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
718
-     * @param bool        $cache        whether to cache the instantiated object for reuse
719
-     * @param bool        $from_db      some classes are instantiated from the db
720
-     *                                  and thus call a different method to instantiate
721
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
722
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
723
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
724
-     *                                  object = class loaded and instantiated successfully.
725
-     *                                  bool = fail or success when $load_only is true
726
-     * @throws InvalidInterfaceException
727
-     * @throws InvalidDataTypeException
728
-     * @throws EE_Error
729
-     * @throws ReflectionException
730
-     * @throws InvalidArgumentException
731
-     */
732
-    public function create(
733
-        $class_name = false,
734
-        $arguments = array(),
735
-        $cache = false,
736
-        $from_db = false,
737
-        $load_only = false,
738
-        $addon = false
739
-    ) {
740
-        $class_name = ltrim($class_name, '\\');
741
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
742
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
743
-        // if a non-FQCN was passed, then
744
-        // verifyClassExists() might return an object
745
-        // or it could return null if the class just could not be found anywhere
746
-        if ($class_exists instanceof $class_name || $class_exists === null) {
747
-            // either way, return the results
748
-            return $class_exists;
749
-        }
750
-        $class_name = $class_exists;
751
-        // if we're only loading the class and it already exists, then let's just return true immediately
752
-        if ($load_only) {
753
-            return true;
754
-        }
755
-        $addon = $addon ? 'addon' : '';
756
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
757
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
758
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
759
-        if ($this->_cache_on && $cache && ! $load_only) {
760
-            // return object if it's already cached
761
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
762
-            if ($cached_class !== null) {
763
-                return $cached_class;
764
-            }
765
-        }// obtain the loader method from the dependency map
766
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
767
-        if ($loader instanceof Closure) {
768
-            $class_obj = $loader($arguments);
769
-        } else {
770
-            if ($loader && method_exists($this, $loader)) {
771
-                $class_obj = $this->{$loader}($class_name, $arguments);
772
-            } else {
773
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
774
-            }
775
-        }
776
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
777
-            // save it for later... kinda like gum  { : $
778
-            $this->_set_cached_class(
779
-                $class_obj,
780
-                $class_name,
781
-                $addon,
782
-                $from_db,
783
-                $arguments
784
-            );
785
-        }
786
-        $this->_cache_on = true;
787
-        return $class_obj;
788
-    }
789
-
790
-
791
-    /**
792
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
793
-     *
794
-     * @param string|object $class_name
795
-     * @param array         $arguments
796
-     * @param int           $attempt
797
-     * @return mixed
798
-     */
799
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
800
-    {
801
-        if (is_object($class_name) || class_exists($class_name)) {
802
-            return $class_name;
803
-        }
804
-        switch ($attempt) {
805
-            case 1:
806
-                // if it's a FQCN then maybe the class is registered with a preceding \
807
-                $class_name = strpos($class_name, '\\') !== false
808
-                    ? '\\' . ltrim($class_name, '\\')
809
-                    : $class_name;
810
-                break;
811
-            case 2:
812
-                //
813
-                $loader = $this->_dependency_map->class_loader($class_name);
814
-                if ($loader && method_exists($this, $loader)) {
815
-                    return $this->{$loader}($class_name, $arguments);
816
-                }
817
-                break;
818
-            case 3:
819
-            default:
820
-                return null;
821
-        }
822
-        $attempt++;
823
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
824
-    }
825
-
826
-
827
-    /**
828
-     * instantiates, caches, and injects dependencies for classes
829
-     *
830
-     * @param array       $file_paths   an array of paths to folders to look in
831
-     * @param string      $class_prefix EE  or EEM or... ???
832
-     * @param bool|string $class_name   $class name
833
-     * @param string      $type         file type - core? class? helper? model?
834
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
835
-     * @param bool        $from_db      some classes are instantiated from the db
836
-     *                                  and thus call a different method to instantiate
837
-     * @param bool        $cache        whether to cache the instantiated object for reuse
838
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
839
-     * @return bool|null|object null = failure to load or instantiate class object.
840
-     *                                  object = class loaded and instantiated successfully.
841
-     *                                  bool = fail or success when $load_only is true
842
-     * @throws EE_Error
843
-     * @throws ReflectionException
844
-     * @throws InvalidInterfaceException
845
-     * @throws InvalidDataTypeException
846
-     * @throws InvalidArgumentException
847
-     */
848
-    protected function _load(
849
-        $file_paths = array(),
850
-        $class_prefix = 'EE_',
851
-        $class_name = false,
852
-        $type = 'class',
853
-        $arguments = array(),
854
-        $from_db = false,
855
-        $cache = true,
856
-        $load_only = false
857
-    ) {
858
-        $class_name = ltrim($class_name, '\\');
859
-        // strip php file extension
860
-        $class_name = str_replace('.php', '', trim($class_name));
861
-        // does the class have a prefix ?
862
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
863
-            // make sure $class_prefix is uppercase
864
-            $class_prefix = strtoupper(trim($class_prefix));
865
-            // add class prefix ONCE!!!
866
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
867
-        }
868
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
869
-        $class_exists = class_exists($class_name, false);
870
-        // if we're only loading the class and it already exists, then let's just return true immediately
871
-        if ($load_only && $class_exists) {
872
-            return true;
873
-        }
874
-        $arguments = is_array($arguments) ? $arguments : array($arguments);
875
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
876
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
877
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
878
-        if ($this->_cache_on && $cache && ! $load_only) {
879
-            // return object if it's already cached
880
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
881
-            if ($cached_class !== null) {
882
-                return $cached_class;
883
-            }
884
-        }
885
-        // if the class doesn't already exist.. then we need to try and find the file and load it
886
-        if (! $class_exists) {
887
-            // get full path to file
888
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
889
-            // load the file
890
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
891
-            // if we are only loading a file but NOT instantiating an object
892
-            // then return boolean for whether class was loaded or not
893
-            if ($load_only) {
894
-                return $loaded;
895
-            }
896
-            // if an object was expected but loading failed, then return nothing
897
-            if (! $loaded) {
898
-                return null;
899
-            }
900
-        }
901
-        // instantiate the requested object
902
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
903
-        if ($this->_cache_on && $cache) {
904
-            // save it for later... kinda like gum  { : $
905
-            $this->_set_cached_class(
906
-                $class_obj,
907
-                $class_name,
908
-                $class_prefix,
909
-                $from_db,
910
-                $arguments
911
-            );
912
-        }
913
-        $this->_cache_on = true;
914
-        return $class_obj;
915
-    }
916
-
917
-
918
-    /**
919
-     * @param string $class_name
920
-     * @param string $default have to specify something, but not anything that will conflict
921
-     * @return mixed|string
922
-     */
923
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
924
-    {
925
-        return isset($this->_class_abbreviations[ $class_name ])
926
-            ? $this->_class_abbreviations[ $class_name ]
927
-            : $default;
928
-    }
929
-
930
-
931
-    /**
932
-     * attempts to find a cached version of the requested class
933
-     * by looking in the following places:
934
-     *        $this->{$class_abbreviation}            ie:    $this->CART
935
-     *        $this->{$class_name}                        ie:    $this->Some_Class
936
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
937
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
938
-     *
939
-     * @param string $class_name
940
-     * @param string $class_prefix
941
-     * @param array  $arguments
942
-     * @return mixed
943
-     */
944
-    protected function _get_cached_class(
945
-        $class_name,
946
-        $class_prefix = '',
947
-        $arguments = array()
948
-    ) {
949
-        if ($class_name === 'EE_Registry') {
950
-            return $this;
951
-        }
952
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
953
-        // check if class has already been loaded, and return it if it has been
954
-        if (isset($this->{$class_abbreviation})) {
955
-            return $this->{$class_abbreviation};
956
-        }
957
-        $class_name = str_replace('\\', '_', $class_name);
958
-        if (isset($this->{$class_name})) {
959
-            return $this->{$class_name};
960
-        }
961
-        if ($class_prefix === 'addon' && isset($this->addons->{$class_name})) {
962
-            return $this->addons->{$class_name};
963
-        }
964
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
965
-        if (isset($this->LIB->{$object_identifier})) {
966
-            return $this->LIB->{$object_identifier};
967
-        }
968
-        foreach ($this->LIB as $key => $object) {
969
-            if (// request does not contain new arguments and therefore no args identifier
970
-                ! $this->object_identifier->hasArguments($object_identifier)
971
-                // but previously cached class with args was found
972
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
973
-            ) {
974
-                return $object;
975
-            }
976
-        }
977
-        return null;
978
-    }
979
-
980
-
981
-    /**
982
-     * removes a cached version of the requested class
983
-     *
984
-     * @param string  $class_name
985
-     * @param boolean $addon
986
-     * @param array   $arguments
987
-     * @return boolean
988
-     */
989
-    public function clear_cached_class(
990
-        $class_name,
991
-        $addon = false,
992
-        $arguments = array()
993
-    ) {
994
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
995
-        // check if class has already been loaded, and return it if it has been
996
-        if (isset($this->{$class_abbreviation})) {
997
-            $this->{$class_abbreviation} = null;
998
-            return true;
999
-        }
1000
-        $class_name = str_replace('\\', '_', $class_name);
1001
-        if (isset($this->{$class_name})) {
1002
-            $this->{$class_name} = null;
1003
-            return true;
1004
-        }
1005
-        if ($addon && isset($this->addons->{$class_name})) {
1006
-            unset($this->addons->{$class_name});
1007
-            return true;
1008
-        }
1009
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1010
-        if (isset($this->LIB->{$class_name})) {
1011
-            unset($this->LIB->{$class_name});
1012
-            return true;
1013
-        }
1014
-        return false;
1015
-    }
1016
-
1017
-
1018
-    /**
1019
-     * _set_cached_class
1020
-     * attempts to cache the instantiated class locally
1021
-     * in one of the following places, in the following order:
1022
-     *        $this->{class_abbreviation}   ie:    $this->CART
1023
-     *        $this->{$class_name}          ie:    $this->Some_Class
1024
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1025
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1026
-     *
1027
-     * @param object $class_obj
1028
-     * @param string $class_name
1029
-     * @param string $class_prefix
1030
-     * @param bool   $from_db
1031
-     * @param array  $arguments
1032
-     * @return void
1033
-     */
1034
-    protected function _set_cached_class(
1035
-        $class_obj,
1036
-        $class_name,
1037
-        $class_prefix = '',
1038
-        $from_db = false,
1039
-        $arguments = array()
1040
-    ) {
1041
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1042
-            return;
1043
-        }
1044
-        // return newly instantiated class
1045
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1046
-        if ($class_abbreviation) {
1047
-            $this->{$class_abbreviation} = $class_obj;
1048
-            return;
1049
-        }
1050
-        $class_name = str_replace('\\', '_', $class_name);
1051
-        if (property_exists($this, $class_name)) {
1052
-            $this->{$class_name} = $class_obj;
1053
-            return;
1054
-        }
1055
-        if ($class_prefix === 'addon') {
1056
-            $this->addons->{$class_name} = $class_obj;
1057
-            return;
1058
-        }
1059
-        if (! $from_db) {
1060
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1061
-            $this->LIB->{$class_name} = $class_obj;
1062
-        }
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * attempts to find a full valid filepath for the requested class.
1068
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1069
-     * then returns that path if the target file has been found and is readable
1070
-     *
1071
-     * @param string $class_name
1072
-     * @param string $type
1073
-     * @param array  $file_paths
1074
-     * @return string | bool
1075
-     */
1076
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
1077
-    {
1078
-        // make sure $file_paths is an array
1079
-        $file_paths = is_array($file_paths)
1080
-            ? $file_paths
1081
-            : array($file_paths);
1082
-        // cycle thru paths
1083
-        foreach ($file_paths as $key => $file_path) {
1084
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1085
-            $file_path = $file_path
1086
-                ? str_replace(array('/', '\\'), '/', $file_path)
1087
-                : EE_CLASSES;
1088
-            // prep file type
1089
-            $type = ! empty($type)
1090
-                ? trim($type, '.') . '.'
1091
-                : '';
1092
-            // build full file path
1093
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1094
-            // does the file exist and can be read ?
1095
-            if (is_readable($file_paths[ $key ])) {
1096
-                return $file_paths[ $key ];
1097
-            }
1098
-        }
1099
-        return false;
1100
-    }
1101
-
1102
-
1103
-    /**
1104
-     * basically just performs a require_once()
1105
-     * but with some error handling
1106
-     *
1107
-     * @param  string $path
1108
-     * @param  string $class_name
1109
-     * @param  string $type
1110
-     * @param  array  $file_paths
1111
-     * @return bool
1112
-     * @throws EE_Error
1113
-     * @throws ReflectionException
1114
-     */
1115
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1116
-    {
1117
-        $this->resolve_legacy_class_parent($class_name);
1118
-        // don't give up! you gotta...
1119
-        try {
1120
-            // does the file exist and can it be read ?
1121
-            if (! $path) {
1122
-                // just in case the file has already been autoloaded,
1123
-                // but discrepancies in the naming schema are preventing it from
1124
-                // being loaded via one of the EE_Registry::load_*() methods,
1125
-                // then let's try one last hail mary before throwing an exception
1126
-                // and call class_exists() again, but with autoloading turned ON
1127
-                if (class_exists($class_name)) {
1128
-                    return true;
1129
-                }
1130
-                // so sorry, can't find the file
1131
-                throw new EE_Error(
1132
-                    sprintf(
1133
-                        esc_html__(
1134
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1135
-                            'event_espresso'
1136
-                        ),
1137
-                        trim($type, '.'),
1138
-                        $class_name,
1139
-                        '<br />' . implode(',<br />', $file_paths)
1140
-                    )
1141
-                );
1142
-            }
1143
-            // get the file
1144
-            require_once($path);
1145
-            // if the class isn't already declared somewhere
1146
-            if (class_exists($class_name, false) === false) {
1147
-                // so sorry, not a class
1148
-                throw new EE_Error(
1149
-                    sprintf(
1150
-                        esc_html__(
1151
-                            'The %s file %s does not appear to contain the %s Class.',
1152
-                            'event_espresso'
1153
-                        ),
1154
-                        $type,
1155
-                        $path,
1156
-                        $class_name
1157
-                    )
1158
-                );
1159
-            }
1160
-        } catch (EE_Error $e) {
1161
-            $e->get_error();
1162
-            return false;
1163
-        }
1164
-        return true;
1165
-    }
1166
-
1167
-
1168
-    /**
1169
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1170
-     * before their class declaration in order to ensure that the parent class was loaded.
1171
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1172
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1173
-     *
1174
-     * @param string $class_name
1175
-     */
1176
-    protected function resolve_legacy_class_parent($class_name = '')
1177
-    {
1178
-        try {
1179
-            $legacy_parent_class_map = array(
1180
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1181
-            );
1182
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1183
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1184
-            }
1185
-        } catch (Exception $exception) {
1186
-        }
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * _create_object
1192
-     * Attempts to instantiate the requested class via any of the
1193
-     * commonly used instantiation methods employed throughout EE.
1194
-     * The priority for instantiation is as follows:
1195
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1196
-     *        - model objects via their 'new_instance_from_db' method
1197
-     *        - model objects via their 'new_instance' method
1198
-     *        - "singleton" classes" via their 'instance' method
1199
-     *    - standard instantiable classes via their __constructor
1200
-     * Prior to instantiation, if the classname exists in the dependency_map,
1201
-     * then the constructor for the requested class will be examined to determine
1202
-     * if any dependencies exist, and if they can be injected.
1203
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1204
-     *
1205
-     * @param string $class_name
1206
-     * @param array  $arguments
1207
-     * @param string $type
1208
-     * @param bool   $from_db
1209
-     * @return null|object|bool
1210
-     * @throws InvalidArgumentException
1211
-     * @throws InvalidInterfaceException
1212
-     * @throws EE_Error
1213
-     * @throws ReflectionException
1214
-     * @throws InvalidDataTypeException
1215
-     */
1216
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1217
-    {
1218
-        // create reflection
1219
-        $reflector = $this->mirror->getReflectionClass($class_name);
1220
-        // make sure arguments are an array
1221
-        $arguments = is_array($arguments)
1222
-            ? $arguments
1223
-            : array($arguments);
1224
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1225
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1226
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1227
-            ? $arguments
1228
-            : array($arguments);
1229
-        // attempt to inject dependencies ?
1230
-        if ($this->_dependency_map->has($class_name)) {
1231
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1232
-        }
1233
-        // instantiate the class if possible
1234
-        if ($reflector->isAbstract()) {
1235
-            // nothing to instantiate, loading file was enough
1236
-            // does not throw an exception so $instantiation_mode is unused
1237
-            // $instantiation_mode = "1) no constructor abstract class";
1238
-            return true;
1239
-        }
1240
-        if (empty($arguments)
1241
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1242
-            && $reflector->isInstantiable()
1243
-        ) {
1244
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1245
-            // $instantiation_mode = "2) no constructor but instantiable";
1246
-            return $reflector->newInstance();
1247
-        }
1248
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1249
-            // $instantiation_mode = "3) new_instance_from_db()";
1250
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1251
-        }
1252
-        if (method_exists($class_name, 'new_instance')) {
1253
-            // $instantiation_mode = "4) new_instance()";
1254
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1255
-        }
1256
-        if (method_exists($class_name, 'instance')) {
1257
-            // $instantiation_mode = "5) instance()";
1258
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1259
-        }
1260
-        if ($reflector->isInstantiable()) {
1261
-            $args_passed_count = count($arguments);
1262
-            $args_required_count = count($this->mirror->getRequiredParameters($class_name));
1263
-            if ($args_passed_count < $args_required_count) {
1264
-                throw new RuntimeException(
1265
-                    sprintf(
1266
-                        __(
1267
-                            'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1268
-                            'event_espresso'
1269
-                        ),
1270
-                        $class_name,
1271
-                        $args_required_count,
1272
-                        $args_passed_count
1273
-                    )
1274
-                );
1275
-            }
1276
-            // $instantiation_mode = "6) constructor";
1277
-            return $reflector->newInstanceArgs($arguments);
1278
-        }
1279
-        // heh ? something's not right !
1280
-        throw new EE_Error(
1281
-            sprintf(
1282
-                __('The %s file %s could not be instantiated.', 'event_espresso'),
1283
-                $type,
1284
-                $class_name
1285
-            )
1286
-        );
1287
-    }
1288
-
1289
-
1290
-    /**
1291
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1292
-     * @param array $array
1293
-     * @return bool
1294
-     */
1295
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1296
-    {
1297
-        return ! empty($array)
1298
-            ? array_keys($array) === range(0, count($array) - 1)
1299
-            : true;
1300
-    }
1301
-
1302
-
1303
-    /**
1304
-     * _resolve_dependencies
1305
-     * examines the constructor for the requested class to determine
1306
-     * if any dependencies exist, and if they can be injected.
1307
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1308
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1309
-     * For example:
1310
-     *        if attempting to load a class "Foo" with the following constructor:
1311
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1312
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1313
-     *        but only IF they are NOT already present in the incoming arguments array,
1314
-     *        and the correct classes can be loaded
1315
-     *
1316
-     * @param ReflectionClass $reflector
1317
-     * @param string          $class_name
1318
-     * @param array           $arguments
1319
-     * @return array
1320
-     * @throws InvalidArgumentException
1321
-     * @throws InvalidDataTypeException
1322
-     * @throws InvalidInterfaceException
1323
-     * @throws ReflectionException
1324
-     */
1325
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1326
-    {
1327
-        // let's examine the constructor
1328
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1329
-        // whu? huh? nothing?
1330
-        if (! $constructor) {
1331
-            return $arguments;
1332
-        }
1333
-        // get constructor parameters
1334
-        $params = $this->mirror->getParametersFromReflection($reflector);
1335
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1336
-        $argument_keys = array_keys($arguments);
1337
-        // now loop thru all of the constructors expected parameters
1338
-        foreach ($params as $index => $param) {
1339
-            try {
1340
-                // is this a dependency for a specific class ?
1341
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1342
-            } catch (ReflectionException $exception) {
1343
-                // uh-oh... most likely a legacy class that has not been autoloaded
1344
-                // let's try to derive the classname from what we have now
1345
-                // and hope that the property var name is close to the class name
1346
-                $param_class = $param->getName();
1347
-                $param_class = str_replace('_', ' ', $param_class);
1348
-                $param_class = ucwords($param_class);
1349
-                $param_class = str_replace(' ', '_', $param_class);
1350
-            }
1351
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1352
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1353
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1354
-                : $param_class;
1355
-            if (// param is not even a class
1356
-                $param_class === null
1357
-                // and something already exists in the incoming arguments for this param
1358
-                && array_key_exists($index, $argument_keys)
1359
-                && array_key_exists($argument_keys[ $index ], $arguments)
1360
-            ) {
1361
-                // so let's skip this argument and move on to the next
1362
-                continue;
1363
-            }
1364
-            if (// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1365
-                $param_class !== null
1366
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1367
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1368
-            ) {
1369
-                // skip this argument and move on to the next
1370
-                continue;
1371
-            }
1372
-            if (// parameter is type hinted as a class, and should be injected
1373
-                $param_class !== null
1374
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1375
-            ) {
1376
-                $arguments = $this->_resolve_dependency(
1377
-                    $class_name,
1378
-                    $param_class,
1379
-                    $arguments,
1380
-                    $index
1381
-                );
1382
-            }
1383
-            if (empty($arguments[ $index ])) {
1384
-                $arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1385
-                    $param,
1386
-                    $class_name,
1387
-                    $index
1388
-                );
1389
-            }
1390
-        }
1391
-        return $arguments;
1392
-    }
1393
-
1394
-
1395
-    /**
1396
-     * @param string $class_name
1397
-     * @param string $param_class
1398
-     * @param array  $arguments
1399
-     * @param mixed  $index
1400
-     * @return array
1401
-     * @throws InvalidArgumentException
1402
-     * @throws InvalidInterfaceException
1403
-     * @throws InvalidDataTypeException
1404
-     */
1405
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1406
-    {
1407
-        $dependency = null;
1408
-        // should dependency be loaded from cache ?
1409
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1410
-            $class_name,
1411
-            $param_class
1412
-        );
1413
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1414
-        // we might have a dependency...
1415
-        // let's MAYBE try and find it in our cache if that's what's been requested
1416
-        $cached_class = $cache_on
1417
-            ? $this->_get_cached_class($param_class)
1418
-            : null;
1419
-        // and grab it if it exists
1420
-        if ($cached_class instanceof $param_class) {
1421
-            $dependency = $cached_class;
1422
-        } elseif ($param_class !== $class_name) {
1423
-            // obtain the loader method from the dependency map
1424
-            $loader = $this->_dependency_map->class_loader($param_class);
1425
-            // is loader a custom closure ?
1426
-            if ($loader instanceof Closure) {
1427
-                $dependency = $loader($arguments);
1428
-            } else {
1429
-                // set the cache on property for the recursive loading call
1430
-                $this->_cache_on = $cache_on;
1431
-                // if not, then let's try and load it via the registry
1432
-                if ($loader && method_exists($this, $loader)) {
1433
-                    $dependency = $this->{$loader}($param_class);
1434
-                } else {
1435
-                    $dependency = LoaderFactory::getLoader()->load(
1436
-                        $param_class,
1437
-                        array(),
1438
-                        $cache_on
1439
-                    );
1440
-                }
1441
-            }
1442
-        }
1443
-        // did we successfully find the correct dependency ?
1444
-        if ($dependency instanceof $param_class) {
1445
-            // then let's inject it into the incoming array of arguments at the correct location
1446
-            $arguments[ $index ] = $dependency;
1447
-        }
1448
-        return $arguments;
1449
-    }
1450
-
1451
-
1452
-    /**
1453
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1454
-     *
1455
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1456
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1457
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1458
-     * @param array  $arguments
1459
-     * @return object
1460
-     */
1461
-    public static function factory($classname, $arguments = array())
1462
-    {
1463
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1464
-        if ($loader instanceof Closure) {
1465
-            return $loader($arguments);
1466
-        }
1467
-        if (method_exists(self::instance(), $loader)) {
1468
-            return self::instance()->{$loader}($classname, $arguments);
1469
-        }
1470
-        return null;
1471
-    }
1472
-
1473
-
1474
-    /**
1475
-     * Gets the addon by its class name
1476
-     *
1477
-     * @param string $class_name
1478
-     * @return EE_Addon
1479
-     */
1480
-    public function getAddon($class_name)
1481
-    {
1482
-        $class_name = str_replace('\\', '_', $class_name);
1483
-        if (isset($this->addons->{$class_name})) {
1484
-            return $this->addons->{$class_name};
1485
-        } else {
1486
-            return null;
1487
-        }
1488
-    }
1489
-
1490
-
1491
-    /**
1492
-     * removes the addon from the internal cache
1493
-     *
1494
-     * @param string $class_name
1495
-     * @return void
1496
-     */
1497
-    public function removeAddon($class_name)
1498
-    {
1499
-        $class_name = str_replace('\\', '_', $class_name);
1500
-        unset($this->addons->{$class_name});
1501
-    }
1502
-
1503
-
1504
-    /**
1505
-     * Gets the addon by its name/slug (not classname. For that, just
1506
-     * use the get_addon() method above
1507
-     *
1508
-     * @param string $name
1509
-     * @return EE_Addon
1510
-     */
1511
-    public function get_addon_by_name($name)
1512
-    {
1513
-        foreach ($this->addons as $addon) {
1514
-            if ($addon->name() === $name) {
1515
-                return $addon;
1516
-            }
1517
-        }
1518
-        return null;
1519
-    }
1520
-
1521
-
1522
-    /**
1523
-     * Gets an array of all the registered addons, where the keys are their names.
1524
-     * (ie, what each returns for their name() function)
1525
-     * They're already available on EE_Registry::instance()->addons as properties,
1526
-     * where each property's name is the addon's classname,
1527
-     * So if you just want to get the addon by classname,
1528
-     * OR use the get_addon() method above.
1529
-     * PLEASE  NOTE:
1530
-     * addons with Fully Qualified Class Names
1531
-     * have had the namespace separators converted to underscores,
1532
-     * so a classname like Fully\Qualified\ClassName
1533
-     * would have been converted to Fully_Qualified_ClassName
1534
-     *
1535
-     * @return EE_Addon[] where the KEYS are the addon's name()
1536
-     */
1537
-    public function get_addons_by_name()
1538
-    {
1539
-        $addons = array();
1540
-        foreach ($this->addons as $addon) {
1541
-            $addons[ $addon->name() ] = $addon;
1542
-        }
1543
-        return $addons;
1544
-    }
1545
-
1546
-
1547
-    /**
1548
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1549
-     * a stale copy of it around
1550
-     *
1551
-     * @param string $model_name
1552
-     * @return \EEM_Base
1553
-     * @throws \EE_Error
1554
-     */
1555
-    public function reset_model($model_name)
1556
-    {
1557
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1558
-            ? "EEM_{$model_name}"
1559
-            : $model_name;
1560
-        if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1561
-            return null;
1562
-        }
1563
-        // get that model reset it and make sure we nuke the old reference to it
1564
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name
1565
-            && is_callable(
1566
-                array($model_class_name, 'reset')
1567
-            )) {
1568
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1569
-        } else {
1570
-            throw new EE_Error(
1571
-                sprintf(
1572
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1573
-                    $model_name
1574
-                )
1575
-            );
1576
-        }
1577
-        return $this->LIB->{$model_class_name};
1578
-    }
1579
-
1580
-
1581
-    /**
1582
-     * Resets the registry.
1583
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1584
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1585
-     * - $_dependency_map
1586
-     * - $_class_abbreviations
1587
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1588
-     * - $REQ:  Still on the same request so no need to change.
1589
-     * - $CAP: There is no site specific state in the EE_Capability class.
1590
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1591
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1592
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1593
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1594
-     *             switch or on the restore.
1595
-     * - $modules
1596
-     * - $shortcodes
1597
-     * - $widgets
1598
-     *
1599
-     * @param boolean $hard             [deprecated]
1600
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1601
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1602
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1603
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1604
-     *                                  client
1605
-     *                                  code instead can just change the model context to a different blog id if
1606
-     *                                  necessary
1607
-     * @return EE_Registry
1608
-     * @throws InvalidInterfaceException
1609
-     * @throws InvalidDataTypeException
1610
-     * @throws EE_Error
1611
-     * @throws ReflectionException
1612
-     * @throws InvalidArgumentException
1613
-     */
1614
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1615
-    {
1616
-        $instance = self::instance();
1617
-        $instance->_cache_on = true;
1618
-        // reset some "special" classes
1619
-        EEH_Activation::reset();
1620
-        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1621
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1622
-        $instance->CART = null;
1623
-        $instance->MRM = null;
1624
-        $instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1625
-            'EventEspresso\core\services\assets\Registry'
1626
-        );
1627
-        // messages reset
1628
-        EED_Messages::reset();
1629
-        // handle of objects cached on LIB
1630
-        foreach (array('LIB', 'modules') as $cache) {
1631
-            foreach ($instance->{$cache} as $class_name => $class) {
1632
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1633
-                    unset($instance->{$cache}->{$class_name});
1634
-                }
1635
-            }
1636
-        }
1637
-        return $instance;
1638
-    }
1639
-
1640
-
1641
-    /**
1642
-     * if passed object implements ResettableInterface, then call it's reset() method
1643
-     * if passed object implements InterminableInterface, then return false,
1644
-     * to indicate that it should NOT be cleared from the Registry cache
1645
-     *
1646
-     * @param      $object
1647
-     * @param bool $reset_models
1648
-     * @return bool returns true if cached object should be unset
1649
-     */
1650
-    private static function _reset_and_unset_object($object, $reset_models)
1651
-    {
1652
-        if (! is_object($object)) {
1653
-            // don't unset anything that's not an object
1654
-            return false;
1655
-        }
1656
-        if ($object instanceof EED_Module) {
1657
-            $object::reset();
1658
-            // don't unset modules
1659
-            return false;
1660
-        }
1661
-        if ($object instanceof ResettableInterface) {
1662
-            if ($object instanceof EEM_Base) {
1663
-                if ($reset_models) {
1664
-                    $object->reset();
1665
-                    return true;
1666
-                }
1667
-                return false;
1668
-            }
1669
-            $object->reset();
1670
-            return true;
1671
-        }
1672
-        if (! $object instanceof InterminableInterface) {
1673
-            return true;
1674
-        }
1675
-        return false;
1676
-    }
1677
-
1678
-
1679
-    /**
1680
-     * Gets all the custom post type models defined
1681
-     *
1682
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1683
-     */
1684
-    public function cpt_models()
1685
-    {
1686
-        $cpt_models = array();
1687
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1688
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1689
-                $cpt_models[ $short_name ] = $classname;
1690
-            }
1691
-        }
1692
-        return $cpt_models;
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * @return \EE_Config
1698
-     */
1699
-    public static function CFG()
1700
-    {
1701
-        return self::instance()->CFG;
1702
-    }
1703
-
1704
-
1705
-    /**
1706
-     * @deprecated 4.9.62.p
1707
-     * @param string $class_name
1708
-     * @return ReflectionClass
1709
-     * @throws ReflectionException
1710
-     * @throws InvalidDataTypeException
1711
-     */
1712
-    public function get_ReflectionClass($class_name)
1713
-    {
1714
-        return $this->mirror->getReflectionClass($class_name);
1715
-    }
26
+	/**
27
+	 * @var EE_Registry $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var EE_Dependency_Map $_dependency_map
33
+	 */
34
+	protected $_dependency_map;
35
+
36
+	/**
37
+	 * @var Mirror
38
+	 */
39
+	private $mirror;
40
+
41
+	/**
42
+	 * @var ClassInterfaceCache $class_cache
43
+	 */
44
+	private $class_cache;
45
+
46
+	/**
47
+	 * @var array $_class_abbreviations
48
+	 */
49
+	protected $_class_abbreviations = array();
50
+
51
+	/**
52
+	 * @var CommandBusInterface $BUS
53
+	 */
54
+	public $BUS;
55
+
56
+	/**
57
+	 * @var EE_Cart $CART
58
+	 */
59
+	public $CART;
60
+
61
+	/**
62
+	 * @var EE_Config $CFG
63
+	 */
64
+	public $CFG;
65
+
66
+	/**
67
+	 * @var EE_Network_Config $NET_CFG
68
+	 */
69
+	public $NET_CFG;
70
+
71
+	/**
72
+	 * StdClass object for storing library classes in
73
+	 *
74
+	 * @var RegistryContainer $LIB
75
+	 */
76
+	public $LIB;
77
+
78
+	/**
79
+	 * @var EE_Request_Handler $REQ
80
+	 */
81
+	public $REQ;
82
+
83
+	/**
84
+	 * @var EE_Session $SSN
85
+	 */
86
+	public $SSN;
87
+
88
+	/**
89
+	 * @since 4.5.0
90
+	 * @var EE_Capabilities $CAP
91
+	 */
92
+	public $CAP;
93
+
94
+	/**
95
+	 * @since 4.9.0
96
+	 * @var EE_Message_Resource_Manager $MRM
97
+	 */
98
+	public $MRM;
99
+
100
+	/**
101
+	 * @var Registry $AssetsRegistry
102
+	 */
103
+	public $AssetsRegistry;
104
+
105
+	/**
106
+	 * StdClass object for holding addons which have registered themselves to work with EE core
107
+	 *
108
+	 * @var EE_Addon[] $addons
109
+	 */
110
+	public $addons;
111
+
112
+	/**
113
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
114
+	 *
115
+	 * @var EEM_Base[] $models
116
+	 */
117
+	public $models = array();
118
+
119
+	/**
120
+	 * @var EED_Module[] $modules
121
+	 */
122
+	public $modules;
123
+
124
+	/**
125
+	 * @var EES_Shortcode[] $shortcodes
126
+	 */
127
+	public $shortcodes;
128
+
129
+	/**
130
+	 * @var WP_Widget[] $widgets
131
+	 */
132
+	public $widgets;
133
+
134
+	/**
135
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
136
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
137
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
138
+	 * classnames (eg "EEM_Event")
139
+	 *
140
+	 * @var array $non_abstract_db_models
141
+	 */
142
+	public $non_abstract_db_models = array();
143
+
144
+	/**
145
+	 * internationalization for JS strings
146
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
147
+	 *    in js file:  var translatedString = eei18n.string_key;
148
+	 *
149
+	 * @var array $i18n_js_strings
150
+	 */
151
+	public static $i18n_js_strings = array();
152
+
153
+	/**
154
+	 * $main_file - path to espresso.php
155
+	 *
156
+	 * @var array $main_file
157
+	 */
158
+	public $main_file;
159
+
160
+	/**
161
+	 * array of ReflectionClass objects where the key is the class name
162
+	 *
163
+	 * @deprecated 4.9.62.p
164
+	 * @var ReflectionClass[] $_reflectors
165
+	 */
166
+	public $_reflectors;
167
+
168
+	/**
169
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
170
+	 *
171
+	 * @var boolean $_cache_on
172
+	 */
173
+	protected $_cache_on = true;
174
+
175
+	/**
176
+	 * @var ObjectIdentifier
177
+	 */
178
+	private $object_identifier;
179
+
180
+
181
+	/**
182
+	 * @singleton method used to instantiate class object
183
+	 * @param EE_Dependency_Map|null   $dependency_map
184
+	 * @param Mirror|null              $mirror
185
+	 * @param ClassInterfaceCache|null $class_cache
186
+	 * @param ObjectIdentifier|null    $object_identifier
187
+	 * @return EE_Registry instance
188
+	 */
189
+	public static function instance(
190
+		EE_Dependency_Map $dependency_map = null,
191
+		Mirror $mirror = null,
192
+		ClassInterfaceCache $class_cache = null,
193
+		ObjectIdentifier $object_identifier = null
194
+	) {
195
+		// check if class object is instantiated
196
+		if (! self::$_instance instanceof EE_Registry
197
+			&& $dependency_map instanceof EE_Dependency_Map
198
+			&& $mirror instanceof Mirror
199
+			&& $class_cache instanceof ClassInterfaceCache
200
+			&& $object_identifier instanceof ObjectIdentifier
201
+		) {
202
+			self::$_instance = new self(
203
+				$dependency_map,
204
+				$mirror,
205
+				$class_cache,
206
+				$object_identifier
207
+			);
208
+		}
209
+		return self::$_instance;
210
+	}
211
+
212
+
213
+	/**
214
+	 * protected constructor to prevent direct creation
215
+	 *
216
+	 * @Constructor
217
+	 * @param  EE_Dependency_Map  $dependency_map
218
+	 * @param Mirror              $mirror
219
+	 * @param ClassInterfaceCache $class_cache
220
+	 * @param ObjectIdentifier    $object_identifier
221
+	 */
222
+	protected function __construct(
223
+		EE_Dependency_Map $dependency_map,
224
+		Mirror $mirror,
225
+		ClassInterfaceCache $class_cache,
226
+		ObjectIdentifier $object_identifier
227
+	) {
228
+		$this->_dependency_map = $dependency_map;
229
+		$this->mirror = $mirror;
230
+		$this->class_cache = $class_cache;
231
+		$this->object_identifier = $object_identifier;
232
+		// $registry_container = new RegistryContainer();
233
+		$this->LIB = new RegistryContainer();
234
+		$this->addons = new RegistryContainer();
235
+		$this->modules = new RegistryContainer();
236
+		$this->shortcodes = new RegistryContainer();
237
+		$this->widgets = new RegistryContainer();
238
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
239
+	}
240
+
241
+
242
+	/**
243
+	 * initialize
244
+	 *
245
+	 * @throws OutOfBoundsException
246
+	 * @throws InvalidArgumentException
247
+	 * @throws InvalidInterfaceException
248
+	 * @throws InvalidDataTypeException
249
+	 * @throws EE_Error
250
+	 * @throws ReflectionException
251
+	 */
252
+	public function initialize()
253
+	{
254
+		$this->_class_abbreviations = apply_filters(
255
+			'FHEE__EE_Registry____construct___class_abbreviations',
256
+			array(
257
+				'EE_Config'                                       => 'CFG',
258
+				'EE_Session'                                      => 'SSN',
259
+				'EE_Capabilities'                                 => 'CAP',
260
+				'EE_Cart'                                         => 'CART',
261
+				'EE_Network_Config'                               => 'NET_CFG',
262
+				'EE_Request_Handler'                              => 'REQ',
263
+				'EE_Message_Resource_Manager'                     => 'MRM',
264
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
265
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
266
+			)
267
+		);
268
+		$this->load_core('Base', array(), true);
269
+		// add our request and response objects to the cache
270
+		$request_loader = $this->_dependency_map->class_loader(
271
+			'EventEspresso\core\services\request\Request'
272
+		);
273
+		$this->_set_cached_class(
274
+			$request_loader(),
275
+			'EventEspresso\core\services\request\Request'
276
+		);
277
+		$response_loader = $this->_dependency_map->class_loader(
278
+			'EventEspresso\core\services\request\Response'
279
+		);
280
+		$this->_set_cached_class(
281
+			$response_loader(),
282
+			'EventEspresso\core\services\request\Response'
283
+		);
284
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return void
290
+	 */
291
+	public function init()
292
+	{
293
+		// Get current page protocol
294
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
295
+		// Output admin-ajax.php URL with same protocol as current page
296
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
297
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
298
+	}
299
+
300
+
301
+	/**
302
+	 * localize_i18n_js_strings
303
+	 *
304
+	 * @return string
305
+	 */
306
+	public static function localize_i18n_js_strings()
307
+	{
308
+		$i18n_js_strings = (array) self::$i18n_js_strings;
309
+		foreach ($i18n_js_strings as $key => $value) {
310
+			if (is_scalar($value)) {
311
+				$i18n_js_strings[ $key ] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
+			}
313
+		}
314
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param mixed string | EED_Module $module
320
+	 * @throws OutOfBoundsException
321
+	 * @throws InvalidArgumentException
322
+	 * @throws InvalidInterfaceException
323
+	 * @throws InvalidDataTypeException
324
+	 * @throws EE_Error
325
+	 * @throws ReflectionException
326
+	 */
327
+	public function add_module($module)
328
+	{
329
+		if ($module instanceof EED_Module) {
330
+			$module_class = get_class($module);
331
+			$this->modules->{$module_class} = $module;
332
+		} else {
333
+			if (! class_exists('EE_Module_Request_Router', false)) {
334
+				$this->load_core('Module_Request_Router');
335
+			}
336
+			EE_Module_Request_Router::module_factory($module);
337
+		}
338
+	}
339
+
340
+
341
+	/**
342
+	 * @param string $module_name
343
+	 * @return mixed EED_Module | NULL
344
+	 */
345
+	public function get_module($module_name = '')
346
+	{
347
+		return isset($this->modules->{$module_name})
348
+			? $this->modules->{$module_name}
349
+			: null;
350
+	}
351
+
352
+
353
+	/**
354
+	 * loads core classes - must be singletons
355
+	 *
356
+	 * @param string $class_name - simple class name ie: session
357
+	 * @param mixed  $arguments
358
+	 * @param bool   $load_only
359
+	 * @return mixed
360
+	 * @throws InvalidInterfaceException
361
+	 * @throws InvalidDataTypeException
362
+	 * @throws EE_Error
363
+	 * @throws ReflectionException
364
+	 * @throws InvalidArgumentException
365
+	 */
366
+	public function load_core($class_name, $arguments = array(), $load_only = false)
367
+	{
368
+		$core_paths = apply_filters(
369
+			'FHEE__EE_Registry__load_core__core_paths',
370
+			array(
371
+				EE_CORE,
372
+				EE_ADMIN,
373
+				EE_CPTS,
374
+				EE_CORE . 'data_migration_scripts/',
375
+				EE_CORE . 'capabilities/',
376
+				EE_CORE . 'request_stack/',
377
+				EE_CORE . 'middleware/',
378
+			)
379
+		);
380
+		// retrieve instantiated class
381
+		return $this->_load(
382
+			$core_paths,
383
+			'EE_',
384
+			$class_name,
385
+			'core',
386
+			$arguments,
387
+			false,
388
+			true,
389
+			$load_only
390
+		);
391
+	}
392
+
393
+
394
+	/**
395
+	 * loads service classes
396
+	 *
397
+	 * @param string $class_name - simple class name ie: session
398
+	 * @param mixed  $arguments
399
+	 * @param bool   $load_only
400
+	 * @return mixed
401
+	 * @throws InvalidInterfaceException
402
+	 * @throws InvalidDataTypeException
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 * @throws InvalidArgumentException
406
+	 */
407
+	public function load_service($class_name, $arguments = array(), $load_only = false)
408
+	{
409
+		$service_paths = apply_filters(
410
+			'FHEE__EE_Registry__load_service__service_paths',
411
+			array(
412
+				EE_CORE . 'services/',
413
+			)
414
+		);
415
+		// retrieve instantiated class
416
+		return $this->_load(
417
+			$service_paths,
418
+			'EE_',
419
+			$class_name,
420
+			'class',
421
+			$arguments,
422
+			false,
423
+			true,
424
+			$load_only
425
+		);
426
+	}
427
+
428
+
429
+	/**
430
+	 * loads data_migration_scripts
431
+	 *
432
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
433
+	 * @param mixed  $arguments
434
+	 * @return EE_Data_Migration_Script_Base|mixed
435
+	 * @throws InvalidInterfaceException
436
+	 * @throws InvalidDataTypeException
437
+	 * @throws EE_Error
438
+	 * @throws ReflectionException
439
+	 * @throws InvalidArgumentException
440
+	 */
441
+	public function load_dms($class_name, $arguments = array())
442
+	{
443
+		// retrieve instantiated class
444
+		return $this->_load(
445
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
446
+			'EE_DMS_',
447
+			$class_name,
448
+			'dms',
449
+			$arguments,
450
+			false,
451
+			false
452
+		);
453
+	}
454
+
455
+
456
+	/**
457
+	 * loads object creating classes - must be singletons
458
+	 *
459
+	 * @param string $class_name - simple class name ie: attendee
460
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
461
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
462
+	 *                           instantiate
463
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
464
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
465
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
466
+	 *                           (default)
467
+	 * @return EE_Base_Class | bool
468
+	 * @throws InvalidInterfaceException
469
+	 * @throws InvalidDataTypeException
470
+	 * @throws EE_Error
471
+	 * @throws ReflectionException
472
+	 * @throws InvalidArgumentException
473
+	 */
474
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
475
+	{
476
+		$paths = apply_filters(
477
+			'FHEE__EE_Registry__load_class__paths',
478
+			array(
479
+				EE_CORE,
480
+				EE_CLASSES,
481
+				EE_BUSINESS,
482
+			)
483
+		);
484
+		// retrieve instantiated class
485
+		return $this->_load(
486
+			$paths,
487
+			'EE_',
488
+			$class_name,
489
+			'class',
490
+			$arguments,
491
+			$from_db,
492
+			$cache,
493
+			$load_only
494
+		);
495
+	}
496
+
497
+
498
+	/**
499
+	 * loads helper classes - must be singletons
500
+	 *
501
+	 * @param string $class_name - simple class name ie: price
502
+	 * @param mixed  $arguments
503
+	 * @param bool   $load_only
504
+	 * @return EEH_Base | bool
505
+	 * @throws InvalidInterfaceException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws EE_Error
508
+	 * @throws ReflectionException
509
+	 * @throws InvalidArgumentException
510
+	 */
511
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
512
+	{
513
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
514
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
515
+		// retrieve instantiated class
516
+		return $this->_load(
517
+			$helper_paths,
518
+			'EEH_',
519
+			$class_name,
520
+			'helper',
521
+			$arguments,
522
+			false,
523
+			true,
524
+			$load_only
525
+		);
526
+	}
527
+
528
+
529
+	/**
530
+	 * loads core classes - must be singletons
531
+	 *
532
+	 * @param string $class_name - simple class name ie: session
533
+	 * @param mixed  $arguments
534
+	 * @param bool   $load_only
535
+	 * @param bool   $cache      whether to cache the object or not.
536
+	 * @return mixed
537
+	 * @throws InvalidInterfaceException
538
+	 * @throws InvalidDataTypeException
539
+	 * @throws EE_Error
540
+	 * @throws ReflectionException
541
+	 * @throws InvalidArgumentException
542
+	 */
543
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
544
+	{
545
+		$paths = array(
546
+			EE_LIBRARIES,
547
+			EE_LIBRARIES . 'messages/',
548
+			EE_LIBRARIES . 'shortcodes/',
549
+			EE_LIBRARIES . 'qtips/',
550
+			EE_LIBRARIES . 'payment_methods/',
551
+		);
552
+		// retrieve instantiated class
553
+		return $this->_load(
554
+			$paths,
555
+			'EE_',
556
+			$class_name,
557
+			'lib',
558
+			$arguments,
559
+			false,
560
+			$cache,
561
+			$load_only
562
+		);
563
+	}
564
+
565
+
566
+	/**
567
+	 * loads model classes - must be singletons
568
+	 *
569
+	 * @param string $class_name - simple class name ie: price
570
+	 * @param mixed  $arguments
571
+	 * @param bool   $load_only
572
+	 * @return EEM_Base | bool
573
+	 * @throws InvalidInterfaceException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws EE_Error
576
+	 * @throws ReflectionException
577
+	 * @throws InvalidArgumentException
578
+	 */
579
+	public function load_model($class_name, $arguments = array(), $load_only = false)
580
+	{
581
+		$paths = apply_filters(
582
+			'FHEE__EE_Registry__load_model__paths',
583
+			array(
584
+				EE_MODELS,
585
+				EE_CORE,
586
+			)
587
+		);
588
+		// retrieve instantiated class
589
+		return $this->_load(
590
+			$paths,
591
+			'EEM_',
592
+			$class_name,
593
+			'model',
594
+			$arguments,
595
+			false,
596
+			true,
597
+			$load_only
598
+		);
599
+	}
600
+
601
+
602
+	/**
603
+	 * loads model classes - must be singletons
604
+	 *
605
+	 * @param string $class_name - simple class name ie: price
606
+	 * @param mixed  $arguments
607
+	 * @param bool   $load_only
608
+	 * @return mixed | bool
609
+	 * @throws InvalidInterfaceException
610
+	 * @throws InvalidDataTypeException
611
+	 * @throws EE_Error
612
+	 * @throws ReflectionException
613
+	 * @throws InvalidArgumentException
614
+	 */
615
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
616
+	{
617
+		$paths = array(
618
+			EE_MODELS . 'fields/',
619
+			EE_MODELS . 'helpers/',
620
+			EE_MODELS . 'relations/',
621
+			EE_MODELS . 'strategies/',
622
+		);
623
+		// retrieve instantiated class
624
+		return $this->_load(
625
+			$paths,
626
+			'EE_',
627
+			$class_name,
628
+			'',
629
+			$arguments,
630
+			false,
631
+			true,
632
+			$load_only
633
+		);
634
+	}
635
+
636
+
637
+	/**
638
+	 * Determines if $model_name is the name of an actual EE model.
639
+	 *
640
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
641
+	 * @return boolean
642
+	 */
643
+	public function is_model_name($model_name)
644
+	{
645
+		return isset($this->models[ $model_name ]);
646
+	}
647
+
648
+
649
+	/**
650
+	 * generic class loader
651
+	 *
652
+	 * @param string $path_to_file - directory path to file location, not including filename
653
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
654
+	 * @param string $type         - file type - core? class? helper? model?
655
+	 * @param mixed  $arguments
656
+	 * @param bool   $load_only
657
+	 * @return mixed
658
+	 * @throws InvalidInterfaceException
659
+	 * @throws InvalidDataTypeException
660
+	 * @throws EE_Error
661
+	 * @throws ReflectionException
662
+	 * @throws InvalidArgumentException
663
+	 */
664
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
665
+	{
666
+		// retrieve instantiated class
667
+		return $this->_load(
668
+			$path_to_file,
669
+			'',
670
+			$file_name,
671
+			$type,
672
+			$arguments,
673
+			false,
674
+			true,
675
+			$load_only
676
+		);
677
+	}
678
+
679
+
680
+	/**
681
+	 * @param string $path_to_file - directory path to file location, not including filename
682
+	 * @param string $class_name   - full class name  ie:  My_Class
683
+	 * @param string $type         - file type - core? class? helper? model?
684
+	 * @param mixed  $arguments
685
+	 * @param bool   $load_only
686
+	 * @return bool|EE_Addon|object
687
+	 * @throws InvalidInterfaceException
688
+	 * @throws InvalidDataTypeException
689
+	 * @throws EE_Error
690
+	 * @throws ReflectionException
691
+	 * @throws InvalidArgumentException
692
+	 */
693
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
694
+	{
695
+		// retrieve instantiated class
696
+		return $this->_load(
697
+			$path_to_file,
698
+			'addon',
699
+			$class_name,
700
+			$type,
701
+			$arguments,
702
+			false,
703
+			true,
704
+			$load_only
705
+		);
706
+	}
707
+
708
+
709
+	/**
710
+	 * instantiates, caches, and automatically resolves dependencies
711
+	 * for classes that use a Fully Qualified Class Name.
712
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
713
+	 * then you need to use one of the existing load_*() methods
714
+	 * which can resolve the classname and filepath from the passed arguments
715
+	 *
716
+	 * @param bool|string $class_name   Fully Qualified Class Name
717
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
718
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
719
+	 * @param bool        $from_db      some classes are instantiated from the db
720
+	 *                                  and thus call a different method to instantiate
721
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
722
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
723
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
724
+	 *                                  object = class loaded and instantiated successfully.
725
+	 *                                  bool = fail or success when $load_only is true
726
+	 * @throws InvalidInterfaceException
727
+	 * @throws InvalidDataTypeException
728
+	 * @throws EE_Error
729
+	 * @throws ReflectionException
730
+	 * @throws InvalidArgumentException
731
+	 */
732
+	public function create(
733
+		$class_name = false,
734
+		$arguments = array(),
735
+		$cache = false,
736
+		$from_db = false,
737
+		$load_only = false,
738
+		$addon = false
739
+	) {
740
+		$class_name = ltrim($class_name, '\\');
741
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
742
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
743
+		// if a non-FQCN was passed, then
744
+		// verifyClassExists() might return an object
745
+		// or it could return null if the class just could not be found anywhere
746
+		if ($class_exists instanceof $class_name || $class_exists === null) {
747
+			// either way, return the results
748
+			return $class_exists;
749
+		}
750
+		$class_name = $class_exists;
751
+		// if we're only loading the class and it already exists, then let's just return true immediately
752
+		if ($load_only) {
753
+			return true;
754
+		}
755
+		$addon = $addon ? 'addon' : '';
756
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
757
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
758
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
759
+		if ($this->_cache_on && $cache && ! $load_only) {
760
+			// return object if it's already cached
761
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
762
+			if ($cached_class !== null) {
763
+				return $cached_class;
764
+			}
765
+		}// obtain the loader method from the dependency map
766
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
767
+		if ($loader instanceof Closure) {
768
+			$class_obj = $loader($arguments);
769
+		} else {
770
+			if ($loader && method_exists($this, $loader)) {
771
+				$class_obj = $this->{$loader}($class_name, $arguments);
772
+			} else {
773
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
774
+			}
775
+		}
776
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
777
+			// save it for later... kinda like gum  { : $
778
+			$this->_set_cached_class(
779
+				$class_obj,
780
+				$class_name,
781
+				$addon,
782
+				$from_db,
783
+				$arguments
784
+			);
785
+		}
786
+		$this->_cache_on = true;
787
+		return $class_obj;
788
+	}
789
+
790
+
791
+	/**
792
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
793
+	 *
794
+	 * @param string|object $class_name
795
+	 * @param array         $arguments
796
+	 * @param int           $attempt
797
+	 * @return mixed
798
+	 */
799
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
800
+	{
801
+		if (is_object($class_name) || class_exists($class_name)) {
802
+			return $class_name;
803
+		}
804
+		switch ($attempt) {
805
+			case 1:
806
+				// if it's a FQCN then maybe the class is registered with a preceding \
807
+				$class_name = strpos($class_name, '\\') !== false
808
+					? '\\' . ltrim($class_name, '\\')
809
+					: $class_name;
810
+				break;
811
+			case 2:
812
+				//
813
+				$loader = $this->_dependency_map->class_loader($class_name);
814
+				if ($loader && method_exists($this, $loader)) {
815
+					return $this->{$loader}($class_name, $arguments);
816
+				}
817
+				break;
818
+			case 3:
819
+			default:
820
+				return null;
821
+		}
822
+		$attempt++;
823
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
824
+	}
825
+
826
+
827
+	/**
828
+	 * instantiates, caches, and injects dependencies for classes
829
+	 *
830
+	 * @param array       $file_paths   an array of paths to folders to look in
831
+	 * @param string      $class_prefix EE  or EEM or... ???
832
+	 * @param bool|string $class_name   $class name
833
+	 * @param string      $type         file type - core? class? helper? model?
834
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
835
+	 * @param bool        $from_db      some classes are instantiated from the db
836
+	 *                                  and thus call a different method to instantiate
837
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
838
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
839
+	 * @return bool|null|object null = failure to load or instantiate class object.
840
+	 *                                  object = class loaded and instantiated successfully.
841
+	 *                                  bool = fail or success when $load_only is true
842
+	 * @throws EE_Error
843
+	 * @throws ReflectionException
844
+	 * @throws InvalidInterfaceException
845
+	 * @throws InvalidDataTypeException
846
+	 * @throws InvalidArgumentException
847
+	 */
848
+	protected function _load(
849
+		$file_paths = array(),
850
+		$class_prefix = 'EE_',
851
+		$class_name = false,
852
+		$type = 'class',
853
+		$arguments = array(),
854
+		$from_db = false,
855
+		$cache = true,
856
+		$load_only = false
857
+	) {
858
+		$class_name = ltrim($class_name, '\\');
859
+		// strip php file extension
860
+		$class_name = str_replace('.php', '', trim($class_name));
861
+		// does the class have a prefix ?
862
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
863
+			// make sure $class_prefix is uppercase
864
+			$class_prefix = strtoupper(trim($class_prefix));
865
+			// add class prefix ONCE!!!
866
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
867
+		}
868
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
869
+		$class_exists = class_exists($class_name, false);
870
+		// if we're only loading the class and it already exists, then let's just return true immediately
871
+		if ($load_only && $class_exists) {
872
+			return true;
873
+		}
874
+		$arguments = is_array($arguments) ? $arguments : array($arguments);
875
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
876
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
877
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
878
+		if ($this->_cache_on && $cache && ! $load_only) {
879
+			// return object if it's already cached
880
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
881
+			if ($cached_class !== null) {
882
+				return $cached_class;
883
+			}
884
+		}
885
+		// if the class doesn't already exist.. then we need to try and find the file and load it
886
+		if (! $class_exists) {
887
+			// get full path to file
888
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
889
+			// load the file
890
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
891
+			// if we are only loading a file but NOT instantiating an object
892
+			// then return boolean for whether class was loaded or not
893
+			if ($load_only) {
894
+				return $loaded;
895
+			}
896
+			// if an object was expected but loading failed, then return nothing
897
+			if (! $loaded) {
898
+				return null;
899
+			}
900
+		}
901
+		// instantiate the requested object
902
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
903
+		if ($this->_cache_on && $cache) {
904
+			// save it for later... kinda like gum  { : $
905
+			$this->_set_cached_class(
906
+				$class_obj,
907
+				$class_name,
908
+				$class_prefix,
909
+				$from_db,
910
+				$arguments
911
+			);
912
+		}
913
+		$this->_cache_on = true;
914
+		return $class_obj;
915
+	}
916
+
917
+
918
+	/**
919
+	 * @param string $class_name
920
+	 * @param string $default have to specify something, but not anything that will conflict
921
+	 * @return mixed|string
922
+	 */
923
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
924
+	{
925
+		return isset($this->_class_abbreviations[ $class_name ])
926
+			? $this->_class_abbreviations[ $class_name ]
927
+			: $default;
928
+	}
929
+
930
+
931
+	/**
932
+	 * attempts to find a cached version of the requested class
933
+	 * by looking in the following places:
934
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
935
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
936
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
937
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
938
+	 *
939
+	 * @param string $class_name
940
+	 * @param string $class_prefix
941
+	 * @param array  $arguments
942
+	 * @return mixed
943
+	 */
944
+	protected function _get_cached_class(
945
+		$class_name,
946
+		$class_prefix = '',
947
+		$arguments = array()
948
+	) {
949
+		if ($class_name === 'EE_Registry') {
950
+			return $this;
951
+		}
952
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
953
+		// check if class has already been loaded, and return it if it has been
954
+		if (isset($this->{$class_abbreviation})) {
955
+			return $this->{$class_abbreviation};
956
+		}
957
+		$class_name = str_replace('\\', '_', $class_name);
958
+		if (isset($this->{$class_name})) {
959
+			return $this->{$class_name};
960
+		}
961
+		if ($class_prefix === 'addon' && isset($this->addons->{$class_name})) {
962
+			return $this->addons->{$class_name};
963
+		}
964
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
965
+		if (isset($this->LIB->{$object_identifier})) {
966
+			return $this->LIB->{$object_identifier};
967
+		}
968
+		foreach ($this->LIB as $key => $object) {
969
+			if (// request does not contain new arguments and therefore no args identifier
970
+				! $this->object_identifier->hasArguments($object_identifier)
971
+				// but previously cached class with args was found
972
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
973
+			) {
974
+				return $object;
975
+			}
976
+		}
977
+		return null;
978
+	}
979
+
980
+
981
+	/**
982
+	 * removes a cached version of the requested class
983
+	 *
984
+	 * @param string  $class_name
985
+	 * @param boolean $addon
986
+	 * @param array   $arguments
987
+	 * @return boolean
988
+	 */
989
+	public function clear_cached_class(
990
+		$class_name,
991
+		$addon = false,
992
+		$arguments = array()
993
+	) {
994
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
995
+		// check if class has already been loaded, and return it if it has been
996
+		if (isset($this->{$class_abbreviation})) {
997
+			$this->{$class_abbreviation} = null;
998
+			return true;
999
+		}
1000
+		$class_name = str_replace('\\', '_', $class_name);
1001
+		if (isset($this->{$class_name})) {
1002
+			$this->{$class_name} = null;
1003
+			return true;
1004
+		}
1005
+		if ($addon && isset($this->addons->{$class_name})) {
1006
+			unset($this->addons->{$class_name});
1007
+			return true;
1008
+		}
1009
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1010
+		if (isset($this->LIB->{$class_name})) {
1011
+			unset($this->LIB->{$class_name});
1012
+			return true;
1013
+		}
1014
+		return false;
1015
+	}
1016
+
1017
+
1018
+	/**
1019
+	 * _set_cached_class
1020
+	 * attempts to cache the instantiated class locally
1021
+	 * in one of the following places, in the following order:
1022
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1023
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1024
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1025
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1026
+	 *
1027
+	 * @param object $class_obj
1028
+	 * @param string $class_name
1029
+	 * @param string $class_prefix
1030
+	 * @param bool   $from_db
1031
+	 * @param array  $arguments
1032
+	 * @return void
1033
+	 */
1034
+	protected function _set_cached_class(
1035
+		$class_obj,
1036
+		$class_name,
1037
+		$class_prefix = '',
1038
+		$from_db = false,
1039
+		$arguments = array()
1040
+	) {
1041
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1042
+			return;
1043
+		}
1044
+		// return newly instantiated class
1045
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1046
+		if ($class_abbreviation) {
1047
+			$this->{$class_abbreviation} = $class_obj;
1048
+			return;
1049
+		}
1050
+		$class_name = str_replace('\\', '_', $class_name);
1051
+		if (property_exists($this, $class_name)) {
1052
+			$this->{$class_name} = $class_obj;
1053
+			return;
1054
+		}
1055
+		if ($class_prefix === 'addon') {
1056
+			$this->addons->{$class_name} = $class_obj;
1057
+			return;
1058
+		}
1059
+		if (! $from_db) {
1060
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1061
+			$this->LIB->{$class_name} = $class_obj;
1062
+		}
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * attempts to find a full valid filepath for the requested class.
1068
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1069
+	 * then returns that path if the target file has been found and is readable
1070
+	 *
1071
+	 * @param string $class_name
1072
+	 * @param string $type
1073
+	 * @param array  $file_paths
1074
+	 * @return string | bool
1075
+	 */
1076
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
1077
+	{
1078
+		// make sure $file_paths is an array
1079
+		$file_paths = is_array($file_paths)
1080
+			? $file_paths
1081
+			: array($file_paths);
1082
+		// cycle thru paths
1083
+		foreach ($file_paths as $key => $file_path) {
1084
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1085
+			$file_path = $file_path
1086
+				? str_replace(array('/', '\\'), '/', $file_path)
1087
+				: EE_CLASSES;
1088
+			// prep file type
1089
+			$type = ! empty($type)
1090
+				? trim($type, '.') . '.'
1091
+				: '';
1092
+			// build full file path
1093
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1094
+			// does the file exist and can be read ?
1095
+			if (is_readable($file_paths[ $key ])) {
1096
+				return $file_paths[ $key ];
1097
+			}
1098
+		}
1099
+		return false;
1100
+	}
1101
+
1102
+
1103
+	/**
1104
+	 * basically just performs a require_once()
1105
+	 * but with some error handling
1106
+	 *
1107
+	 * @param  string $path
1108
+	 * @param  string $class_name
1109
+	 * @param  string $type
1110
+	 * @param  array  $file_paths
1111
+	 * @return bool
1112
+	 * @throws EE_Error
1113
+	 * @throws ReflectionException
1114
+	 */
1115
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1116
+	{
1117
+		$this->resolve_legacy_class_parent($class_name);
1118
+		// don't give up! you gotta...
1119
+		try {
1120
+			// does the file exist and can it be read ?
1121
+			if (! $path) {
1122
+				// just in case the file has already been autoloaded,
1123
+				// but discrepancies in the naming schema are preventing it from
1124
+				// being loaded via one of the EE_Registry::load_*() methods,
1125
+				// then let's try one last hail mary before throwing an exception
1126
+				// and call class_exists() again, but with autoloading turned ON
1127
+				if (class_exists($class_name)) {
1128
+					return true;
1129
+				}
1130
+				// so sorry, can't find the file
1131
+				throw new EE_Error(
1132
+					sprintf(
1133
+						esc_html__(
1134
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1135
+							'event_espresso'
1136
+						),
1137
+						trim($type, '.'),
1138
+						$class_name,
1139
+						'<br />' . implode(',<br />', $file_paths)
1140
+					)
1141
+				);
1142
+			}
1143
+			// get the file
1144
+			require_once($path);
1145
+			// if the class isn't already declared somewhere
1146
+			if (class_exists($class_name, false) === false) {
1147
+				// so sorry, not a class
1148
+				throw new EE_Error(
1149
+					sprintf(
1150
+						esc_html__(
1151
+							'The %s file %s does not appear to contain the %s Class.',
1152
+							'event_espresso'
1153
+						),
1154
+						$type,
1155
+						$path,
1156
+						$class_name
1157
+					)
1158
+				);
1159
+			}
1160
+		} catch (EE_Error $e) {
1161
+			$e->get_error();
1162
+			return false;
1163
+		}
1164
+		return true;
1165
+	}
1166
+
1167
+
1168
+	/**
1169
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1170
+	 * before their class declaration in order to ensure that the parent class was loaded.
1171
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1172
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1173
+	 *
1174
+	 * @param string $class_name
1175
+	 */
1176
+	protected function resolve_legacy_class_parent($class_name = '')
1177
+	{
1178
+		try {
1179
+			$legacy_parent_class_map = array(
1180
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1181
+			);
1182
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1183
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1184
+			}
1185
+		} catch (Exception $exception) {
1186
+		}
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * _create_object
1192
+	 * Attempts to instantiate the requested class via any of the
1193
+	 * commonly used instantiation methods employed throughout EE.
1194
+	 * The priority for instantiation is as follows:
1195
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1196
+	 *        - model objects via their 'new_instance_from_db' method
1197
+	 *        - model objects via their 'new_instance' method
1198
+	 *        - "singleton" classes" via their 'instance' method
1199
+	 *    - standard instantiable classes via their __constructor
1200
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1201
+	 * then the constructor for the requested class will be examined to determine
1202
+	 * if any dependencies exist, and if they can be injected.
1203
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1204
+	 *
1205
+	 * @param string $class_name
1206
+	 * @param array  $arguments
1207
+	 * @param string $type
1208
+	 * @param bool   $from_db
1209
+	 * @return null|object|bool
1210
+	 * @throws InvalidArgumentException
1211
+	 * @throws InvalidInterfaceException
1212
+	 * @throws EE_Error
1213
+	 * @throws ReflectionException
1214
+	 * @throws InvalidDataTypeException
1215
+	 */
1216
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1217
+	{
1218
+		// create reflection
1219
+		$reflector = $this->mirror->getReflectionClass($class_name);
1220
+		// make sure arguments are an array
1221
+		$arguments = is_array($arguments)
1222
+			? $arguments
1223
+			: array($arguments);
1224
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1225
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1226
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1227
+			? $arguments
1228
+			: array($arguments);
1229
+		// attempt to inject dependencies ?
1230
+		if ($this->_dependency_map->has($class_name)) {
1231
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1232
+		}
1233
+		// instantiate the class if possible
1234
+		if ($reflector->isAbstract()) {
1235
+			// nothing to instantiate, loading file was enough
1236
+			// does not throw an exception so $instantiation_mode is unused
1237
+			// $instantiation_mode = "1) no constructor abstract class";
1238
+			return true;
1239
+		}
1240
+		if (empty($arguments)
1241
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1242
+			&& $reflector->isInstantiable()
1243
+		) {
1244
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1245
+			// $instantiation_mode = "2) no constructor but instantiable";
1246
+			return $reflector->newInstance();
1247
+		}
1248
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1249
+			// $instantiation_mode = "3) new_instance_from_db()";
1250
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1251
+		}
1252
+		if (method_exists($class_name, 'new_instance')) {
1253
+			// $instantiation_mode = "4) new_instance()";
1254
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1255
+		}
1256
+		if (method_exists($class_name, 'instance')) {
1257
+			// $instantiation_mode = "5) instance()";
1258
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1259
+		}
1260
+		if ($reflector->isInstantiable()) {
1261
+			$args_passed_count = count($arguments);
1262
+			$args_required_count = count($this->mirror->getRequiredParameters($class_name));
1263
+			if ($args_passed_count < $args_required_count) {
1264
+				throw new RuntimeException(
1265
+					sprintf(
1266
+						__(
1267
+							'Invalid arguments supplied for the %1$s class, %2$s were required but %3$s were passed.',
1268
+							'event_espresso'
1269
+						),
1270
+						$class_name,
1271
+						$args_required_count,
1272
+						$args_passed_count
1273
+					)
1274
+				);
1275
+			}
1276
+			// $instantiation_mode = "6) constructor";
1277
+			return $reflector->newInstanceArgs($arguments);
1278
+		}
1279
+		// heh ? something's not right !
1280
+		throw new EE_Error(
1281
+			sprintf(
1282
+				__('The %s file %s could not be instantiated.', 'event_espresso'),
1283
+				$type,
1284
+				$class_name
1285
+			)
1286
+		);
1287
+	}
1288
+
1289
+
1290
+	/**
1291
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1292
+	 * @param array $array
1293
+	 * @return bool
1294
+	 */
1295
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1296
+	{
1297
+		return ! empty($array)
1298
+			? array_keys($array) === range(0, count($array) - 1)
1299
+			: true;
1300
+	}
1301
+
1302
+
1303
+	/**
1304
+	 * _resolve_dependencies
1305
+	 * examines the constructor for the requested class to determine
1306
+	 * if any dependencies exist, and if they can be injected.
1307
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1308
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1309
+	 * For example:
1310
+	 *        if attempting to load a class "Foo" with the following constructor:
1311
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1312
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1313
+	 *        but only IF they are NOT already present in the incoming arguments array,
1314
+	 *        and the correct classes can be loaded
1315
+	 *
1316
+	 * @param ReflectionClass $reflector
1317
+	 * @param string          $class_name
1318
+	 * @param array           $arguments
1319
+	 * @return array
1320
+	 * @throws InvalidArgumentException
1321
+	 * @throws InvalidDataTypeException
1322
+	 * @throws InvalidInterfaceException
1323
+	 * @throws ReflectionException
1324
+	 */
1325
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1326
+	{
1327
+		// let's examine the constructor
1328
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1329
+		// whu? huh? nothing?
1330
+		if (! $constructor) {
1331
+			return $arguments;
1332
+		}
1333
+		// get constructor parameters
1334
+		$params = $this->mirror->getParametersFromReflection($reflector);
1335
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1336
+		$argument_keys = array_keys($arguments);
1337
+		// now loop thru all of the constructors expected parameters
1338
+		foreach ($params as $index => $param) {
1339
+			try {
1340
+				// is this a dependency for a specific class ?
1341
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1342
+			} catch (ReflectionException $exception) {
1343
+				// uh-oh... most likely a legacy class that has not been autoloaded
1344
+				// let's try to derive the classname from what we have now
1345
+				// and hope that the property var name is close to the class name
1346
+				$param_class = $param->getName();
1347
+				$param_class = str_replace('_', ' ', $param_class);
1348
+				$param_class = ucwords($param_class);
1349
+				$param_class = str_replace(' ', '_', $param_class);
1350
+			}
1351
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1352
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1353
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1354
+				: $param_class;
1355
+			if (// param is not even a class
1356
+				$param_class === null
1357
+				// and something already exists in the incoming arguments for this param
1358
+				&& array_key_exists($index, $argument_keys)
1359
+				&& array_key_exists($argument_keys[ $index ], $arguments)
1360
+			) {
1361
+				// so let's skip this argument and move on to the next
1362
+				continue;
1363
+			}
1364
+			if (// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1365
+				$param_class !== null
1366
+				&& isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1367
+				&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1368
+			) {
1369
+				// skip this argument and move on to the next
1370
+				continue;
1371
+			}
1372
+			if (// parameter is type hinted as a class, and should be injected
1373
+				$param_class !== null
1374
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1375
+			) {
1376
+				$arguments = $this->_resolve_dependency(
1377
+					$class_name,
1378
+					$param_class,
1379
+					$arguments,
1380
+					$index
1381
+				);
1382
+			}
1383
+			if (empty($arguments[ $index ])) {
1384
+				$arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1385
+					$param,
1386
+					$class_name,
1387
+					$index
1388
+				);
1389
+			}
1390
+		}
1391
+		return $arguments;
1392
+	}
1393
+
1394
+
1395
+	/**
1396
+	 * @param string $class_name
1397
+	 * @param string $param_class
1398
+	 * @param array  $arguments
1399
+	 * @param mixed  $index
1400
+	 * @return array
1401
+	 * @throws InvalidArgumentException
1402
+	 * @throws InvalidInterfaceException
1403
+	 * @throws InvalidDataTypeException
1404
+	 */
1405
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1406
+	{
1407
+		$dependency = null;
1408
+		// should dependency be loaded from cache ?
1409
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1410
+			$class_name,
1411
+			$param_class
1412
+		);
1413
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1414
+		// we might have a dependency...
1415
+		// let's MAYBE try and find it in our cache if that's what's been requested
1416
+		$cached_class = $cache_on
1417
+			? $this->_get_cached_class($param_class)
1418
+			: null;
1419
+		// and grab it if it exists
1420
+		if ($cached_class instanceof $param_class) {
1421
+			$dependency = $cached_class;
1422
+		} elseif ($param_class !== $class_name) {
1423
+			// obtain the loader method from the dependency map
1424
+			$loader = $this->_dependency_map->class_loader($param_class);
1425
+			// is loader a custom closure ?
1426
+			if ($loader instanceof Closure) {
1427
+				$dependency = $loader($arguments);
1428
+			} else {
1429
+				// set the cache on property for the recursive loading call
1430
+				$this->_cache_on = $cache_on;
1431
+				// if not, then let's try and load it via the registry
1432
+				if ($loader && method_exists($this, $loader)) {
1433
+					$dependency = $this->{$loader}($param_class);
1434
+				} else {
1435
+					$dependency = LoaderFactory::getLoader()->load(
1436
+						$param_class,
1437
+						array(),
1438
+						$cache_on
1439
+					);
1440
+				}
1441
+			}
1442
+		}
1443
+		// did we successfully find the correct dependency ?
1444
+		if ($dependency instanceof $param_class) {
1445
+			// then let's inject it into the incoming array of arguments at the correct location
1446
+			$arguments[ $index ] = $dependency;
1447
+		}
1448
+		return $arguments;
1449
+	}
1450
+
1451
+
1452
+	/**
1453
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1454
+	 *
1455
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1456
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1457
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1458
+	 * @param array  $arguments
1459
+	 * @return object
1460
+	 */
1461
+	public static function factory($classname, $arguments = array())
1462
+	{
1463
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1464
+		if ($loader instanceof Closure) {
1465
+			return $loader($arguments);
1466
+		}
1467
+		if (method_exists(self::instance(), $loader)) {
1468
+			return self::instance()->{$loader}($classname, $arguments);
1469
+		}
1470
+		return null;
1471
+	}
1472
+
1473
+
1474
+	/**
1475
+	 * Gets the addon by its class name
1476
+	 *
1477
+	 * @param string $class_name
1478
+	 * @return EE_Addon
1479
+	 */
1480
+	public function getAddon($class_name)
1481
+	{
1482
+		$class_name = str_replace('\\', '_', $class_name);
1483
+		if (isset($this->addons->{$class_name})) {
1484
+			return $this->addons->{$class_name};
1485
+		} else {
1486
+			return null;
1487
+		}
1488
+	}
1489
+
1490
+
1491
+	/**
1492
+	 * removes the addon from the internal cache
1493
+	 *
1494
+	 * @param string $class_name
1495
+	 * @return void
1496
+	 */
1497
+	public function removeAddon($class_name)
1498
+	{
1499
+		$class_name = str_replace('\\', '_', $class_name);
1500
+		unset($this->addons->{$class_name});
1501
+	}
1502
+
1503
+
1504
+	/**
1505
+	 * Gets the addon by its name/slug (not classname. For that, just
1506
+	 * use the get_addon() method above
1507
+	 *
1508
+	 * @param string $name
1509
+	 * @return EE_Addon
1510
+	 */
1511
+	public function get_addon_by_name($name)
1512
+	{
1513
+		foreach ($this->addons as $addon) {
1514
+			if ($addon->name() === $name) {
1515
+				return $addon;
1516
+			}
1517
+		}
1518
+		return null;
1519
+	}
1520
+
1521
+
1522
+	/**
1523
+	 * Gets an array of all the registered addons, where the keys are their names.
1524
+	 * (ie, what each returns for their name() function)
1525
+	 * They're already available on EE_Registry::instance()->addons as properties,
1526
+	 * where each property's name is the addon's classname,
1527
+	 * So if you just want to get the addon by classname,
1528
+	 * OR use the get_addon() method above.
1529
+	 * PLEASE  NOTE:
1530
+	 * addons with Fully Qualified Class Names
1531
+	 * have had the namespace separators converted to underscores,
1532
+	 * so a classname like Fully\Qualified\ClassName
1533
+	 * would have been converted to Fully_Qualified_ClassName
1534
+	 *
1535
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1536
+	 */
1537
+	public function get_addons_by_name()
1538
+	{
1539
+		$addons = array();
1540
+		foreach ($this->addons as $addon) {
1541
+			$addons[ $addon->name() ] = $addon;
1542
+		}
1543
+		return $addons;
1544
+	}
1545
+
1546
+
1547
+	/**
1548
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1549
+	 * a stale copy of it around
1550
+	 *
1551
+	 * @param string $model_name
1552
+	 * @return \EEM_Base
1553
+	 * @throws \EE_Error
1554
+	 */
1555
+	public function reset_model($model_name)
1556
+	{
1557
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1558
+			? "EEM_{$model_name}"
1559
+			: $model_name;
1560
+		if (! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1561
+			return null;
1562
+		}
1563
+		// get that model reset it and make sure we nuke the old reference to it
1564
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name
1565
+			&& is_callable(
1566
+				array($model_class_name, 'reset')
1567
+			)) {
1568
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1569
+		} else {
1570
+			throw new EE_Error(
1571
+				sprintf(
1572
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1573
+					$model_name
1574
+				)
1575
+			);
1576
+		}
1577
+		return $this->LIB->{$model_class_name};
1578
+	}
1579
+
1580
+
1581
+	/**
1582
+	 * Resets the registry.
1583
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1584
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1585
+	 * - $_dependency_map
1586
+	 * - $_class_abbreviations
1587
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1588
+	 * - $REQ:  Still on the same request so no need to change.
1589
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1590
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1591
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1592
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1593
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1594
+	 *             switch or on the restore.
1595
+	 * - $modules
1596
+	 * - $shortcodes
1597
+	 * - $widgets
1598
+	 *
1599
+	 * @param boolean $hard             [deprecated]
1600
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1601
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1602
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1603
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1604
+	 *                                  client
1605
+	 *                                  code instead can just change the model context to a different blog id if
1606
+	 *                                  necessary
1607
+	 * @return EE_Registry
1608
+	 * @throws InvalidInterfaceException
1609
+	 * @throws InvalidDataTypeException
1610
+	 * @throws EE_Error
1611
+	 * @throws ReflectionException
1612
+	 * @throws InvalidArgumentException
1613
+	 */
1614
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1615
+	{
1616
+		$instance = self::instance();
1617
+		$instance->_cache_on = true;
1618
+		// reset some "special" classes
1619
+		EEH_Activation::reset();
1620
+		$hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1621
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1622
+		$instance->CART = null;
1623
+		$instance->MRM = null;
1624
+		$instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1625
+			'EventEspresso\core\services\assets\Registry'
1626
+		);
1627
+		// messages reset
1628
+		EED_Messages::reset();
1629
+		// handle of objects cached on LIB
1630
+		foreach (array('LIB', 'modules') as $cache) {
1631
+			foreach ($instance->{$cache} as $class_name => $class) {
1632
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1633
+					unset($instance->{$cache}->{$class_name});
1634
+				}
1635
+			}
1636
+		}
1637
+		return $instance;
1638
+	}
1639
+
1640
+
1641
+	/**
1642
+	 * if passed object implements ResettableInterface, then call it's reset() method
1643
+	 * if passed object implements InterminableInterface, then return false,
1644
+	 * to indicate that it should NOT be cleared from the Registry cache
1645
+	 *
1646
+	 * @param      $object
1647
+	 * @param bool $reset_models
1648
+	 * @return bool returns true if cached object should be unset
1649
+	 */
1650
+	private static function _reset_and_unset_object($object, $reset_models)
1651
+	{
1652
+		if (! is_object($object)) {
1653
+			// don't unset anything that's not an object
1654
+			return false;
1655
+		}
1656
+		if ($object instanceof EED_Module) {
1657
+			$object::reset();
1658
+			// don't unset modules
1659
+			return false;
1660
+		}
1661
+		if ($object instanceof ResettableInterface) {
1662
+			if ($object instanceof EEM_Base) {
1663
+				if ($reset_models) {
1664
+					$object->reset();
1665
+					return true;
1666
+				}
1667
+				return false;
1668
+			}
1669
+			$object->reset();
1670
+			return true;
1671
+		}
1672
+		if (! $object instanceof InterminableInterface) {
1673
+			return true;
1674
+		}
1675
+		return false;
1676
+	}
1677
+
1678
+
1679
+	/**
1680
+	 * Gets all the custom post type models defined
1681
+	 *
1682
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1683
+	 */
1684
+	public function cpt_models()
1685
+	{
1686
+		$cpt_models = array();
1687
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1688
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1689
+				$cpt_models[ $short_name ] = $classname;
1690
+			}
1691
+		}
1692
+		return $cpt_models;
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * @return \EE_Config
1698
+	 */
1699
+	public static function CFG()
1700
+	{
1701
+		return self::instance()->CFG;
1702
+	}
1703
+
1704
+
1705
+	/**
1706
+	 * @deprecated 4.9.62.p
1707
+	 * @param string $class_name
1708
+	 * @return ReflectionClass
1709
+	 * @throws ReflectionException
1710
+	 * @throws InvalidDataTypeException
1711
+	 */
1712
+	public function get_ReflectionClass($class_name)
1713
+	{
1714
+		return $this->mirror->getReflectionClass($class_name);
1715
+	}
1716 1716
 }
Please login to merge, or discard this patch.
core/EE_System.core.php 2 patches
Indentation   +1240 added lines, -1240 removed lines patch added patch discarded remove patch
@@ -27,1244 +27,1244 @@
 block discarded – undo
27 27
 final class EE_System implements ResettableInterface
28 28
 {
29 29
 
30
-    /**
31
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
-     */
34
-    const req_type_normal = 0;
35
-
36
-    /**
37
-     * Indicates this is a brand new installation of EE so we should install
38
-     * tables and default data etc
39
-     */
40
-    const req_type_new_activation = 1;
41
-
42
-    /**
43
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
-     * and we just exited maintenance mode). We MUST check the database is setup properly
45
-     * and that default data is setup too
46
-     */
47
-    const req_type_reactivation = 2;
48
-
49
-    /**
50
-     * indicates that EE has been upgraded since its previous request.
51
-     * We may have data migration scripts to call and will want to trigger maintenance mode
52
-     */
53
-    const req_type_upgrade = 3;
54
-
55
-    /**
56
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
-     */
58
-    const req_type_downgrade = 4;
59
-
60
-    /**
61
-     * @deprecated since version 4.6.0.dev.006
62
-     * Now whenever a new_activation is detected the request type is still just
63
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
-     * (Specifically, when the migration manager indicates migrations are finished
67
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
-     */
69
-    const req_type_activation_but_not_installed = 5;
70
-
71
-    /**
72
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
-     */
74
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
-
76
-    /**
77
-     * @var EE_System $_instance
78
-     */
79
-    private static $_instance;
80
-
81
-    /**
82
-     * @var EE_Registry $registry
83
-     */
84
-    private $registry;
85
-
86
-    /**
87
-     * @var LoaderInterface $loader
88
-     */
89
-    private $loader;
90
-
91
-    /**
92
-     * @var EE_Capabilities $capabilities
93
-     */
94
-    private $capabilities;
95
-
96
-    /**
97
-     * @var EE_Maintenance_Mode $maintenance_mode
98
-     */
99
-    private $maintenance_mode;
100
-
101
-    /**
102
-     * @var RequestInterface $request
103
-     */
104
-    private $request;
105
-
106
-    /**
107
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
-     *
110
-     * @var int $_req_type
111
-     */
112
-    private $_req_type;
113
-
114
-    /**
115
-     * Whether or not there was a non-micro version change in EE core version during this request
116
-     *
117
-     * @var boolean $_major_version_change
118
-     */
119
-    private $_major_version_change = false;
120
-
121
-    /**
122
-     * @var Router $router
123
-     */
124
-    private $router;
125
-
126
-
127
-    /**
128
-     * @singleton method used to instantiate class object
129
-     * @param LoaderInterface     $loader
130
-     * @param EE_Maintenance_Mode $maintenance_mode
131
-     * @param EE_Registry         $registry
132
-     * @param RequestInterface    $request
133
-     * @param Router $router
134
-     * @return EE_System
135
-     */
136
-    public static function instance(
137
-        LoaderInterface $loader = null,
138
-        EE_Maintenance_Mode $maintenance_mode = null,
139
-        EE_Registry $registry = null,
140
-        RequestInterface $request = null,
141
-        Router $router = null
142
-    ) {
143
-        // check if class object is instantiated
144
-        if (! self::$_instance instanceof EE_System) {
145
-            self::$_instance = new self($loader, $maintenance_mode, $registry, $request, $router);
146
-        }
147
-        return self::$_instance;
148
-    }
149
-
150
-
151
-    /**
152
-     * resets the instance and returns it
153
-     *
154
-     * @return EE_System
155
-     */
156
-    public static function reset()
157
-    {
158
-        self::$_instance->_req_type = null;
159
-        // make sure none of the old hooks are left hanging around
160
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
-        // we need to reset the migration manager in order for it to detect DMSs properly
162
-        EE_Data_Migration_Manager::reset();
163
-        self::instance()->detect_activations_or_upgrades();
164
-        self::instance()->perform_activations_upgrades_and_migrations();
165
-        return self::instance();
166
-    }
167
-
168
-
169
-    /**
170
-     * sets hooks for running rest of system
171
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
-     * starting EE Addons from any other point may lead to problems
173
-     *
174
-     * @param LoaderInterface     $loader
175
-     * @param EE_Maintenance_Mode $maintenance_mode
176
-     * @param EE_Registry         $registry
177
-     * @param RequestInterface    $request
178
-     * @param Router $router
179
-     */
180
-    private function __construct(
181
-        LoaderInterface $loader,
182
-        EE_Maintenance_Mode $maintenance_mode,
183
-        EE_Registry $registry,
184
-        RequestInterface $request,
185
-        Router $router
186
-    ) {
187
-        $this->registry = $registry;
188
-        $this->loader = $loader;
189
-        $this->request = $request;
190
-        $this->router = $router;
191
-        $this->maintenance_mode = $maintenance_mode;
192
-        do_action('AHEE__EE_System__construct__begin', $this);
193
-        add_action(
194
-            'AHEE__EE_Bootstrap__load_espresso_addons',
195
-            array($this, 'loadCapabilities'),
196
-            5
197
-        );
198
-        add_action(
199
-            'AHEE__EE_Bootstrap__load_espresso_addons',
200
-            array($this, 'loadCommandBus'),
201
-            7
202
-        );
203
-        add_action(
204
-            'AHEE__EE_Bootstrap__load_espresso_addons',
205
-            array($this, 'loadPluginApi'),
206
-            9
207
-        );
208
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
209
-        add_action(
210
-            'AHEE__EE_Bootstrap__load_espresso_addons',
211
-            array($this, 'load_espresso_addons')
212
-        );
213
-        // when an ee addon is activated, we want to call the core hook(s) again
214
-        // because the newly-activated addon didn't get a chance to run at all
215
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
216
-        // detect whether install or upgrade
217
-        add_action(
218
-            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
219
-            array($this, 'detect_activations_or_upgrades'),
220
-            3
221
-        );
222
-        // load EE_Config, EE_Textdomain, etc
223
-        add_action(
224
-            'AHEE__EE_Bootstrap__load_core_configuration',
225
-            array($this, 'load_core_configuration'),
226
-            5
227
-        );
228
-        // load specifications for matching routes to current request
229
-        add_action(
230
-            'AHEE__EE_Bootstrap__load_core_configuration',
231
-            array($this, 'loadRouteMatchSpecifications')
232
-        );
233
-        // load EE_Config, EE_Textdomain, etc
234
-        add_action(
235
-            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
236
-            array($this, 'register_shortcodes_modules_and_widgets'),
237
-            7
238
-        );
239
-        // you wanna get going? I wanna get going... let's get going!
240
-        add_action(
241
-            'AHEE__EE_Bootstrap__brew_espresso',
242
-            array($this, 'brew_espresso'),
243
-            9
244
-        );
245
-        // other housekeeping
246
-        // exclude EE critical pages from wp_list_pages
247
-        add_filter(
248
-            'wp_list_pages_excludes',
249
-            array($this, 'remove_pages_from_wp_list_pages'),
250
-            10
251
-        );
252
-        // ALL EE Addons should use the following hook point to attach their initial setup too
253
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
254
-        do_action('AHEE__EE_System__construct__complete', $this);
255
-    }
256
-
257
-
258
-    /**
259
-     * load and setup EE_Capabilities
260
-     *
261
-     * @return void
262
-     */
263
-    public function loadCapabilities()
264
-    {
265
-        $this->capabilities = $this->loader->getShared('EE_Capabilities');
266
-        add_action(
267
-            'AHEE__EE_Capabilities__init_caps__before_initialization',
268
-            function () {
269
-                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
270
-            }
271
-        );
272
-    }
273
-
274
-
275
-    /**
276
-     * create and cache the CommandBus, and also add middleware
277
-     * The CapChecker middleware requires the use of EE_Capabilities
278
-     * which is why we need to load the CommandBus after Caps are set up
279
-     *
280
-     * @return void
281
-     */
282
-    public function loadCommandBus()
283
-    {
284
-        $this->loader->getShared(
285
-            'CommandBusInterface',
286
-            array(
287
-                null,
288
-                apply_filters(
289
-                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
290
-                    array(
291
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
292
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
293
-                    )
294
-                ),
295
-            )
296
-        );
297
-    }
298
-
299
-
300
-    /**
301
-     * @return void
302
-     * @throws EE_Error
303
-     */
304
-    public function loadPluginApi()
305
-    {
306
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
307
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
308
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
309
-        $this->loader->getShared('EE_Request_Handler');
310
-    }
311
-
312
-
313
-    /**
314
-     * @param string $addon_name
315
-     * @param string $version_constant
316
-     * @param string $min_version_required
317
-     * @param string $load_callback
318
-     * @param string $plugin_file_constant
319
-     * @return void
320
-     */
321
-    private function deactivateIncompatibleAddon(
322
-        $addon_name,
323
-        $version_constant,
324
-        $min_version_required,
325
-        $load_callback,
326
-        $plugin_file_constant
327
-    ) {
328
-        if (! defined($version_constant)) {
329
-            return;
330
-        }
331
-        $addon_version = constant($version_constant);
332
-        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
333
-            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
334
-            if (! function_exists('deactivate_plugins')) {
335
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
336
-            }
337
-            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
338
-            unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
339
-            EE_Error::add_error(
340
-                sprintf(
341
-                    esc_html__(
342
-                        'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
343
-                        'event_espresso'
344
-                    ),
345
-                    $addon_name,
346
-                    $min_version_required
347
-                ),
348
-                __FILE__,
349
-                __FUNCTION__ . "({$addon_name})",
350
-                __LINE__
351
-            );
352
-            EE_Error::get_notices(false, true);
353
-        }
354
-    }
355
-
356
-
357
-    /**
358
-     * load_espresso_addons
359
-     * allow addons to load first so that they can set hooks for running DMS's, etc
360
-     * this is hooked into both:
361
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
362
-     *        which runs during the WP 'plugins_loaded' action at priority 5
363
-     *    and the WP 'activate_plugin' hook point
364
-     *
365
-     * @access public
366
-     * @return void
367
-     */
368
-    public function load_espresso_addons()
369
-    {
370
-        $this->deactivateIncompatibleAddon(
371
-            'Wait Lists',
372
-            'EE_WAIT_LISTS_VERSION',
373
-            '1.0.0.beta.074',
374
-            'load_espresso_wait_lists',
375
-            'EE_WAIT_LISTS_PLUGIN_FILE'
376
-        );
377
-        $this->deactivateIncompatibleAddon(
378
-            'Automated Upcoming Event Notifications',
379
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
380
-            '1.0.0.beta.091',
381
-            'load_espresso_automated_upcoming_event_notification',
382
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
383
-        );
384
-        do_action('AHEE__EE_System__load_espresso_addons');
385
-        // if the WP API basic auth plugin isn't already loaded, load it now.
386
-        // We want it for mobile apps. Just include the entire plugin
387
-        // also, don't load the basic auth when a plugin is getting activated, because
388
-        // it could be the basic auth plugin, and it doesn't check if its methods are already defined
389
-        // and causes a fatal error
390
-        if (($this->request->isWordPressApi() || $this->request->isApi())
391
-            && ! $this->request->isActivation()
392
-            && ! function_exists('json_basic_auth_handler')
393
-            && ! function_exists('json_basic_auth_error')
394
-        ) {
395
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth/basic-auth.php';
396
-        }
397
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
398
-    }
399
-
400
-
401
-    /**
402
-     * detect_activations_or_upgrades
403
-     * Checks for activation or upgrade of core first;
404
-     * then also checks if any registered addons have been activated or upgraded
405
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
406
-     * which runs during the WP 'plugins_loaded' action at priority 3
407
-     *
408
-     * @access public
409
-     * @return void
410
-     */
411
-    public function detect_activations_or_upgrades()
412
-    {
413
-        // first off: let's make sure to handle core
414
-        $this->detect_if_activation_or_upgrade();
415
-        foreach ($this->registry->addons as $addon) {
416
-            if ($addon instanceof EE_Addon) {
417
-                // detect teh request type for that addon
418
-                $addon->detect_activation_or_upgrade();
419
-            }
420
-        }
421
-    }
422
-
423
-
424
-    /**
425
-     * detect_if_activation_or_upgrade
426
-     * Takes care of detecting whether this is a brand new install or code upgrade,
427
-     * and either setting up the DB or setting up maintenance mode etc.
428
-     *
429
-     * @access public
430
-     * @return void
431
-     */
432
-    public function detect_if_activation_or_upgrade()
433
-    {
434
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
435
-        // check if db has been updated, or if its a brand-new installation
436
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
437
-        $request_type = $this->detect_req_type($espresso_db_update);
438
-        // EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
439
-        switch ($request_type) {
440
-            case EE_System::req_type_new_activation:
441
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
442
-                $this->_handle_core_version_change($espresso_db_update);
443
-                break;
444
-            case EE_System::req_type_reactivation:
445
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
446
-                $this->_handle_core_version_change($espresso_db_update);
447
-                break;
448
-            case EE_System::req_type_upgrade:
449
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
450
-                // migrations may be required now that we've upgraded
451
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
452
-                $this->_handle_core_version_change($espresso_db_update);
453
-                break;
454
-            case EE_System::req_type_downgrade:
455
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
456
-                // its possible migrations are no longer required
457
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
458
-                $this->_handle_core_version_change($espresso_db_update);
459
-                break;
460
-            case EE_System::req_type_normal:
461
-            default:
462
-                break;
463
-        }
464
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
465
-    }
466
-
467
-
468
-    /**
469
-     * Updates the list of installed versions and sets hooks for
470
-     * initializing the database later during the request
471
-     *
472
-     * @param array $espresso_db_update
473
-     */
474
-    private function _handle_core_version_change($espresso_db_update)
475
-    {
476
-        $this->update_list_of_installed_versions($espresso_db_update);
477
-        // get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
478
-        add_action(
479
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
480
-            array($this, 'initialize_db_if_no_migrations_required')
481
-        );
482
-    }
483
-
484
-
485
-    /**
486
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
487
-     * information about what versions of EE have been installed and activated,
488
-     * NOT necessarily the state of the database
489
-     *
490
-     * @param mixed $espresso_db_update           the value of the WordPress option.
491
-     *                                            If not supplied, fetches it from the options table
492
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
493
-     */
494
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
495
-    {
496
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
497
-        if (! $espresso_db_update) {
498
-            $espresso_db_update = get_option('espresso_db_update');
499
-        }
500
-        // check that option is an array
501
-        if (! is_array($espresso_db_update)) {
502
-            // if option is FALSE, then it never existed
503
-            if ($espresso_db_update === false) {
504
-                // make $espresso_db_update an array and save option with autoload OFF
505
-                $espresso_db_update = array();
506
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
507
-            } else {
508
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
509
-                $espresso_db_update = array($espresso_db_update => array());
510
-                update_option('espresso_db_update', $espresso_db_update);
511
-            }
512
-        } else {
513
-            $corrected_db_update = array();
514
-            // if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
515
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
516
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
517
-                    // the key is an int, and the value IS NOT an array
518
-                    // so it must be numerically-indexed, where values are versions installed...
519
-                    // fix it!
520
-                    $version_string = $should_be_array;
521
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
522
-                } else {
523
-                    // ok it checks out
524
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
525
-                }
526
-            }
527
-            $espresso_db_update = $corrected_db_update;
528
-            update_option('espresso_db_update', $espresso_db_update);
529
-        }
530
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
531
-        return $espresso_db_update;
532
-    }
533
-
534
-
535
-    /**
536
-     * Does the traditional work of setting up the plugin's database and adding default data.
537
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
538
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
539
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
540
-     * so that it will be done when migrations are finished
541
-     *
542
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
543
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
544
-     *                                       This is a resource-intensive job
545
-     *                                       so we prefer to only do it when necessary
546
-     * @return void
547
-     * @throws EE_Error
548
-     */
549
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
550
-    {
551
-        $request_type = $this->detect_req_type();
552
-        // only initialize system if we're not in maintenance mode.
553
-        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
554
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
555
-            $rewrite_rules = $this->loader->getShared(
556
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
557
-            );
558
-            $rewrite_rules->flush();
559
-            if ($verify_schema) {
560
-                EEH_Activation::initialize_db_and_folders();
561
-            }
562
-            EEH_Activation::initialize_db_content();
563
-            EEH_Activation::system_initialization();
564
-            if ($initialize_addons_too) {
565
-                $this->initialize_addons();
566
-            }
567
-        } else {
568
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
569
-        }
570
-        if ($request_type === EE_System::req_type_new_activation
571
-            || $request_type === EE_System::req_type_reactivation
572
-            || (
573
-                $request_type === EE_System::req_type_upgrade
574
-                && $this->is_major_version_change()
575
-            )
576
-        ) {
577
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
578
-        }
579
-    }
580
-
581
-
582
-    /**
583
-     * Initializes the db for all registered addons
584
-     *
585
-     * @throws EE_Error
586
-     */
587
-    public function initialize_addons()
588
-    {
589
-        // foreach registered addon, make sure its db is up-to-date too
590
-        foreach ($this->registry->addons as $addon) {
591
-            if ($addon instanceof EE_Addon) {
592
-                $addon->initialize_db_if_no_migrations_required();
593
-            }
594
-        }
595
-    }
596
-
597
-
598
-    /**
599
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
600
-     *
601
-     * @param    array  $version_history
602
-     * @param    string $current_version_to_add version to be added to the version history
603
-     * @return    boolean success as to whether or not this option was changed
604
-     */
605
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
606
-    {
607
-        if (! $version_history) {
608
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
609
-        }
610
-        if ($current_version_to_add === null) {
611
-            $current_version_to_add = espresso_version();
612
-        }
613
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
614
-        // re-save
615
-        return update_option('espresso_db_update', $version_history);
616
-    }
617
-
618
-
619
-    /**
620
-     * Detects if the current version indicated in the has existed in the list of
621
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
622
-     *
623
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
624
-     *                                  If not supplied, fetches it from the options table.
625
-     *                                  Also, caches its result so later parts of the code can also know whether
626
-     *                                  there's been an update or not. This way we can add the current version to
627
-     *                                  espresso_db_update, but still know if this is a new install or not
628
-     * @return int one of the constants on EE_System::req_type_
629
-     */
630
-    public function detect_req_type($espresso_db_update = null)
631
-    {
632
-        if ($this->_req_type === null) {
633
-            $espresso_db_update = ! empty($espresso_db_update)
634
-                ? $espresso_db_update
635
-                : $this->fix_espresso_db_upgrade_option();
636
-            $this->_req_type = EE_System::detect_req_type_given_activation_history(
637
-                $espresso_db_update,
638
-                'ee_espresso_activation',
639
-                espresso_version()
640
-            );
641
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
642
-            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
643
-        }
644
-        return $this->_req_type;
645
-    }
646
-
647
-
648
-    /**
649
-     * Returns whether or not there was a non-micro version change (ie, change in either
650
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
651
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
652
-     *
653
-     * @param $activation_history
654
-     * @return bool
655
-     */
656
-    private function _detect_major_version_change($activation_history)
657
-    {
658
-        $previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
659
-        $previous_version_parts = explode('.', $previous_version);
660
-        $current_version_parts = explode('.', espresso_version());
661
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
662
-               && (
663
-                   $previous_version_parts[0] !== $current_version_parts[0]
664
-                   || $previous_version_parts[1] !== $current_version_parts[1]
665
-               );
666
-    }
667
-
668
-
669
-    /**
670
-     * Returns true if either the major or minor version of EE changed during this request.
671
-     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
672
-     *
673
-     * @return bool
674
-     */
675
-    public function is_major_version_change()
676
-    {
677
-        return $this->_major_version_change;
678
-    }
679
-
680
-
681
-    /**
682
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
683
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
684
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
685
-     * just activated to (for core that will always be espresso_version())
686
-     *
687
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
688
-     *                                                 ee plugin. for core that's 'espresso_db_update'
689
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
690
-     *                                                 indicate that this plugin was just activated
691
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
692
-     *                                                 espresso_version())
693
-     * @return int one of the constants on EE_System::req_type_*
694
-     */
695
-    public static function detect_req_type_given_activation_history(
696
-        $activation_history_for_addon,
697
-        $activation_indicator_option_name,
698
-        $version_to_upgrade_to
699
-    ) {
700
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
701
-        if ($activation_history_for_addon) {
702
-            // it exists, so this isn't a completely new install
703
-            // check if this version already in that list of previously installed versions
704
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
705
-                // it a version we haven't seen before
706
-                if ($version_is_higher === 1) {
707
-                    $req_type = EE_System::req_type_upgrade;
708
-                } else {
709
-                    $req_type = EE_System::req_type_downgrade;
710
-                }
711
-                delete_option($activation_indicator_option_name);
712
-            } else {
713
-                // its not an update. maybe a reactivation?
714
-                if (get_option($activation_indicator_option_name, false)) {
715
-                    if ($version_is_higher === -1) {
716
-                        $req_type = EE_System::req_type_downgrade;
717
-                    } elseif ($version_is_higher === 0) {
718
-                        // we've seen this version before, but it's an activation. must be a reactivation
719
-                        $req_type = EE_System::req_type_reactivation;
720
-                    } else {// $version_is_higher === 1
721
-                        $req_type = EE_System::req_type_upgrade;
722
-                    }
723
-                    delete_option($activation_indicator_option_name);
724
-                } else {
725
-                    // we've seen this version before and the activation indicate doesn't show it was just activated
726
-                    if ($version_is_higher === -1) {
727
-                        $req_type = EE_System::req_type_downgrade;
728
-                    } elseif ($version_is_higher === 0) {
729
-                        // we've seen this version before and it's not an activation. its normal request
730
-                        $req_type = EE_System::req_type_normal;
731
-                    } else {// $version_is_higher === 1
732
-                        $req_type = EE_System::req_type_upgrade;
733
-                    }
734
-                }
735
-            }
736
-        } else {
737
-            // brand new install
738
-            $req_type = EE_System::req_type_new_activation;
739
-            delete_option($activation_indicator_option_name);
740
-        }
741
-        return $req_type;
742
-    }
743
-
744
-
745
-    /**
746
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
747
-     * the $activation_history_for_addon
748
-     *
749
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
750
-     *                                             sometimes containing 'unknown-date'
751
-     * @param string $version_to_upgrade_to        (current version)
752
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
753
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
754
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
755
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
756
-     */
757
-    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
758
-    {
759
-        // find the most recently-activated version
760
-        $most_recently_active_version =
761
-            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
762
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
763
-    }
764
-
765
-
766
-    /**
767
-     * Gets the most recently active version listed in the activation history,
768
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
769
-     *
770
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
771
-     *                                   sometimes containing 'unknown-date'
772
-     * @return string
773
-     */
774
-    private static function _get_most_recently_active_version_from_activation_history($activation_history)
775
-    {
776
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
777
-        $most_recently_active_version = '0.0.0.dev.000';
778
-        if (is_array($activation_history)) {
779
-            foreach ($activation_history as $version => $times_activated) {
780
-                // check there is a record of when this version was activated. Otherwise,
781
-                // mark it as unknown
782
-                if (! $times_activated) {
783
-                    $times_activated = array('unknown-date');
784
-                }
785
-                if (is_string($times_activated)) {
786
-                    $times_activated = array($times_activated);
787
-                }
788
-                foreach ($times_activated as $an_activation) {
789
-                    if ($an_activation !== 'unknown-date'
790
-                        && $an_activation
791
-                           > $most_recently_active_version_activation) {
792
-                        $most_recently_active_version = $version;
793
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
794
-                            ? '1970-01-01 00:00:00'
795
-                            : $an_activation;
796
-                    }
797
-                }
798
-            }
799
-        }
800
-        return $most_recently_active_version;
801
-    }
802
-
803
-
804
-    /**
805
-     * This redirects to the about EE page after activation
806
-     *
807
-     * @return void
808
-     */
809
-    public function redirect_to_about_ee()
810
-    {
811
-        $notices = EE_Error::get_notices(false);
812
-        // if current user is an admin and it's not an ajax or rest request
813
-        if (! isset($notices['errors'])
814
-            && $this->request->isAdmin()
815
-            && apply_filters(
816
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
817
-                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
818
-            )
819
-        ) {
820
-            $query_params = array('page' => 'espresso_about');
821
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
822
-                $query_params['new_activation'] = true;
823
-            }
824
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
825
-                $query_params['reactivation'] = true;
826
-            }
827
-            $url = add_query_arg($query_params, admin_url('admin.php'));
828
-            wp_safe_redirect($url);
829
-            exit();
830
-        }
831
-    }
832
-
833
-
834
-    /**
835
-     * load_core_configuration
836
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
837
-     * which runs during the WP 'plugins_loaded' action at priority 5
838
-     *
839
-     * @return void
840
-     * @throws ReflectionException
841
-     * @throws Exception
842
-     */
843
-    public function load_core_configuration()
844
-    {
845
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
846
-        $this->loader->getShared('EE_Load_Textdomain');
847
-        // load textdomain
848
-        EE_Load_Textdomain::load_textdomain();
849
-        // load caf stuff a chance to play during the activation process too.
850
-        $this->_maybe_brew_regular();
851
-        // load and setup EE_Config and EE_Network_Config
852
-        $config = $this->loader->getShared('EE_Config');
853
-        $this->loader->getShared('EE_Network_Config');
854
-        // setup autoloaders
855
-        // enable logging?
856
-        if ($config->admin->use_remote_logging) {
857
-            $this->loader->getShared('EE_Log');
858
-        }
859
-        // check for activation errors
860
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
861
-        if ($activation_errors) {
862
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
863
-            update_option('ee_plugin_activation_errors', false);
864
-        }
865
-        // get model names
866
-        $this->_parse_model_names();
867
-        // configure custom post type definitions
868
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
869
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
870
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
871
-    }
872
-
873
-
874
-    /**
875
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
876
-     *
877
-     * @return void
878
-     * @throws ReflectionException
879
-     */
880
-    private function _parse_model_names()
881
-    {
882
-        // get all the files in the EE_MODELS folder that end in .model.php
883
-        $models = glob(EE_MODELS . '*.model.php');
884
-        $model_names = array();
885
-        $non_abstract_db_models = array();
886
-        foreach ($models as $model) {
887
-            // get model classname
888
-            $classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
889
-            $short_name = str_replace('EEM_', '', $classname);
890
-            $reflectionClass = new ReflectionClass($classname);
891
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
892
-                $non_abstract_db_models[ $short_name ] = $classname;
893
-            }
894
-            $model_names[ $short_name ] = $classname;
895
-        }
896
-        $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
897
-        $this->registry->non_abstract_db_models = apply_filters(
898
-            'FHEE__EE_System__parse_implemented_model_names',
899
-            $non_abstract_db_models
900
-        );
901
-    }
902
-
903
-
904
-    /**
905
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
906
-     * that need to be setup before our EE_System launches.
907
-     *
908
-     * @return void
909
-     * @throws DomainException
910
-     * @throws InvalidArgumentException
911
-     * @throws InvalidDataTypeException
912
-     * @throws InvalidInterfaceException
913
-     * @throws InvalidClassException
914
-     * @throws InvalidFilePathException
915
-     */
916
-    private function _maybe_brew_regular()
917
-    {
918
-        /** @var Domain $domain */
919
-        $domain = DomainFactory::getShared(
920
-            new FullyQualifiedName(
921
-                'EventEspresso\core\domain\Domain'
922
-            ),
923
-            array(
924
-                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
925
-                Version::fromString(espresso_version()),
926
-            )
927
-        );
928
-        if ($domain->isCaffeinated()) {
929
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
930
-        }
931
-    }
932
-
933
-
934
-    /**
935
-     * @since 4.9.71.p
936
-     * @throws Exception
937
-     */
938
-    public function loadRouteMatchSpecifications()
939
-    {
940
-        try {
941
-            $this->loader->getShared('EventEspresso\core\services\routing\RouteMatchSpecificationManager');
942
-            $this->loader->getShared('EventEspresso\core\services\routing\RouteCollection');
943
-            $this->router->loadPrimaryRoutes();
944
-        } catch (Exception $exception) {
945
-            new ExceptionStackTraceDisplay($exception);
946
-        }
947
-        do_action('AHEE__EE_System__loadRouteMatchSpecifications');
948
-    }
949
-
950
-
951
-    /**
952
-     * register_shortcodes_modules_and_widgets
953
-     * generate lists of shortcodes and modules, then verify paths and classes
954
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
955
-     * which runs during the WP 'plugins_loaded' action at priority 7
956
-     *
957
-     * @access public
958
-     * @return void
959
-     * @throws Exception
960
-     */
961
-    public function register_shortcodes_modules_and_widgets()
962
-    {
963
-        $this->router->registerShortcodesModulesAndWidgets();
964
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
965
-        // check for addons using old hook point
966
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
967
-            $this->_incompatible_addon_error();
968
-        }
969
-    }
970
-
971
-
972
-    /**
973
-     * _incompatible_addon_error
974
-     *
975
-     * @access public
976
-     * @return void
977
-     */
978
-    private function _incompatible_addon_error()
979
-    {
980
-        // get array of classes hooking into here
981
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
982
-            'AHEE__EE_System__register_shortcodes_modules_and_addons'
983
-        );
984
-        if (! empty($class_names)) {
985
-            $msg = __(
986
-                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
987
-                'event_espresso'
988
-            );
989
-            $msg .= '<ul>';
990
-            foreach ($class_names as $class_name) {
991
-                $msg .= '<li><b>Event Espresso - '
992
-                        . str_replace(
993
-                            array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
994
-                            '',
995
-                            $class_name
996
-                        ) . '</b></li>';
997
-            }
998
-            $msg .= '</ul>';
999
-            $msg .= __(
1000
-                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1001
-                'event_espresso'
1002
-            );
1003
-            // save list of incompatible addons to wp-options for later use
1004
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
1005
-            if (is_admin()) {
1006
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1007
-            }
1008
-        }
1009
-    }
1010
-
1011
-
1012
-    /**
1013
-     * brew_espresso
1014
-     * begins the process of setting hooks for initializing EE in the correct order
1015
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1016
-     * which runs during the WP 'plugins_loaded' action at priority 9
1017
-     *
1018
-     * @return void
1019
-     * @throws Exception
1020
-     */
1021
-    public function brew_espresso()
1022
-    {
1023
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1024
-        // load some final core systems
1025
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
1026
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1027
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1028
-        add_action('init', array($this, 'load_controllers'), 7);
1029
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1030
-        add_action('init', array($this, 'initialize'), 10);
1031
-        add_action('init', array($this, 'initialize_last'), 100);
1032
-        $this->router->brewEspresso();
1033
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1034
-    }
1035
-
1036
-
1037
-    /**
1038
-     *    set_hooks_for_core
1039
-     *
1040
-     * @access public
1041
-     * @return    void
1042
-     * @throws EE_Error
1043
-     */
1044
-    public function set_hooks_for_core()
1045
-    {
1046
-        $this->_deactivate_incompatible_addons();
1047
-        do_action('AHEE__EE_System__set_hooks_for_core');
1048
-        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1049
-        // caps need to be initialized on every request so that capability maps are set.
1050
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1051
-        $this->registry->CAP->init_caps();
1052
-    }
1053
-
1054
-
1055
-    /**
1056
-     * Using the information gathered in EE_System::_incompatible_addon_error,
1057
-     * deactivates any addons considered incompatible with the current version of EE
1058
-     */
1059
-    private function _deactivate_incompatible_addons()
1060
-    {
1061
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
1062
-        if (! empty($incompatible_addons)) {
1063
-            $active_plugins = get_option('active_plugins', array());
1064
-            foreach ($active_plugins as $active_plugin) {
1065
-                foreach ($incompatible_addons as $incompatible_addon) {
1066
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1067
-                        unset($_GET['activate']);
1068
-                        espresso_deactivate_plugin($active_plugin);
1069
-                    }
1070
-                }
1071
-            }
1072
-        }
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     *    perform_activations_upgrades_and_migrations
1078
-     *
1079
-     * @access public
1080
-     * @return    void
1081
-     */
1082
-    public function perform_activations_upgrades_and_migrations()
1083
-    {
1084
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1085
-    }
1086
-
1087
-
1088
-    /**
1089
-     * @return void
1090
-     * @throws DomainException
1091
-     */
1092
-    public function load_CPTs_and_session()
1093
-    {
1094
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1095
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1096
-        $register_custom_taxonomies = $this->loader->getShared(
1097
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1098
-        );
1099
-        $register_custom_taxonomies->registerCustomTaxonomies();
1100
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1101
-        $register_custom_post_types = $this->loader->getShared(
1102
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1103
-        );
1104
-        $register_custom_post_types->registerCustomPostTypes();
1105
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1106
-        $register_custom_taxonomy_terms = $this->loader->getShared(
1107
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1108
-        );
1109
-        $register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1110
-        // load legacy Custom Post Types and Taxonomies
1111
-        $this->loader->getShared('EE_Register_CPTs');
1112
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1113
-    }
1114
-
1115
-
1116
-    /**
1117
-     * load_controllers
1118
-     * this is the best place to load any additional controllers that needs access to EE core.
1119
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1120
-     * time
1121
-     *
1122
-     * @access public
1123
-     * @return void
1124
-     * @throws Exception
1125
-     */
1126
-    public function load_controllers()
1127
-    {
1128
-        do_action('AHEE__EE_System__load_controllers__start');
1129
-        $this->router->loadControllers();
1130
-        do_action('AHEE__EE_System__load_controllers__complete');
1131
-    }
1132
-
1133
-
1134
-    /**
1135
-     * core_loaded_and_ready
1136
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1137
-     *
1138
-     * @access public
1139
-     * @return void
1140
-     * @throws Exception
1141
-     */
1142
-    public function core_loaded_and_ready()
1143
-    {
1144
-        $this->router->coreLoadedAndReady();
1145
-        // integrate WP_Query with the EE models
1146
-        $this->loader->getShared('EE_CPT_Strategy');
1147
-        do_action('AHEE__EE_System__core_loaded_and_ready');
1148
-        // always load template tags, because it's faster than checking if it's a front-end request, and many page
1149
-        // builders require these even on the front-end
1150
-        require_once EE_PUBLIC . 'template_tags.php';
1151
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1152
-    }
1153
-
1154
-
1155
-    /**
1156
-     * initialize
1157
-     * this is the best place to begin initializing client code
1158
-     *
1159
-     * @access public
1160
-     * @return void
1161
-     */
1162
-    public function initialize()
1163
-    {
1164
-        do_action('AHEE__EE_System__initialize');
1165
-    }
1166
-
1167
-
1168
-    /**
1169
-     * initialize_last
1170
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1171
-     * initialize has done so
1172
-     *
1173
-     * @access public
1174
-     * @return void
1175
-     * @throws Exception
1176
-     */
1177
-    public function initialize_last()
1178
-    {
1179
-        do_action('AHEE__EE_System__initialize_last');
1180
-        /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1181
-        $rewrite_rules = $this->loader->getShared(
1182
-            'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1183
-        );
1184
-        $rewrite_rules->flushRewriteRules();
1185
-        $this->router->initializeLast();
1186
-        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * @return void
1192
-     */
1193
-    public function addEspressoToolbar()
1194
-    {
1195
-        $this->loader->getShared(
1196
-            'EventEspresso\core\domain\services\admin\AdminToolBar',
1197
-            array($this->registry->CAP)
1198
-        );
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * do_not_cache
1204
-     * sets no cache headers and defines no cache constants for WP plugins
1205
-     *
1206
-     * @access public
1207
-     * @return void
1208
-     */
1209
-    public static function do_not_cache()
1210
-    {
1211
-        // set no cache constants
1212
-        if (! defined('DONOTCACHEPAGE')) {
1213
-            define('DONOTCACHEPAGE', true);
1214
-        }
1215
-        if (! defined('DONOTCACHCEOBJECT')) {
1216
-            define('DONOTCACHCEOBJECT', true);
1217
-        }
1218
-        if (! defined('DONOTCACHEDB')) {
1219
-            define('DONOTCACHEDB', true);
1220
-        }
1221
-        // add no cache headers
1222
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1223
-        // plus a little extra for nginx and Google Chrome
1224
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1225
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1226
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1227
-    }
1228
-
1229
-
1230
-    /**
1231
-     *    extra_nocache_headers
1232
-     *
1233
-     * @access    public
1234
-     * @param $headers
1235
-     * @return    array
1236
-     */
1237
-    public static function extra_nocache_headers($headers)
1238
-    {
1239
-        // for NGINX
1240
-        $headers['X-Accel-Expires'] = 0;
1241
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1242
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1243
-        return $headers;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     *    nocache_headers
1249
-     *
1250
-     * @access    public
1251
-     * @return    void
1252
-     */
1253
-    public static function nocache_headers()
1254
-    {
1255
-        nocache_headers();
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1261
-     * never returned with the function.
1262
-     *
1263
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1264
-     * @return array
1265
-     */
1266
-    public function remove_pages_from_wp_list_pages($exclude_array)
1267
-    {
1268
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1269
-    }
30
+	/**
31
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
+	 */
34
+	const req_type_normal = 0;
35
+
36
+	/**
37
+	 * Indicates this is a brand new installation of EE so we should install
38
+	 * tables and default data etc
39
+	 */
40
+	const req_type_new_activation = 1;
41
+
42
+	/**
43
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
45
+	 * and that default data is setup too
46
+	 */
47
+	const req_type_reactivation = 2;
48
+
49
+	/**
50
+	 * indicates that EE has been upgraded since its previous request.
51
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
52
+	 */
53
+	const req_type_upgrade = 3;
54
+
55
+	/**
56
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
+	 */
58
+	const req_type_downgrade = 4;
59
+
60
+	/**
61
+	 * @deprecated since version 4.6.0.dev.006
62
+	 * Now whenever a new_activation is detected the request type is still just
63
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
+	 * (Specifically, when the migration manager indicates migrations are finished
67
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
+	 */
69
+	const req_type_activation_but_not_installed = 5;
70
+
71
+	/**
72
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
+	 */
74
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
+
76
+	/**
77
+	 * @var EE_System $_instance
78
+	 */
79
+	private static $_instance;
80
+
81
+	/**
82
+	 * @var EE_Registry $registry
83
+	 */
84
+	private $registry;
85
+
86
+	/**
87
+	 * @var LoaderInterface $loader
88
+	 */
89
+	private $loader;
90
+
91
+	/**
92
+	 * @var EE_Capabilities $capabilities
93
+	 */
94
+	private $capabilities;
95
+
96
+	/**
97
+	 * @var EE_Maintenance_Mode $maintenance_mode
98
+	 */
99
+	private $maintenance_mode;
100
+
101
+	/**
102
+	 * @var RequestInterface $request
103
+	 */
104
+	private $request;
105
+
106
+	/**
107
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
+	 *
110
+	 * @var int $_req_type
111
+	 */
112
+	private $_req_type;
113
+
114
+	/**
115
+	 * Whether or not there was a non-micro version change in EE core version during this request
116
+	 *
117
+	 * @var boolean $_major_version_change
118
+	 */
119
+	private $_major_version_change = false;
120
+
121
+	/**
122
+	 * @var Router $router
123
+	 */
124
+	private $router;
125
+
126
+
127
+	/**
128
+	 * @singleton method used to instantiate class object
129
+	 * @param LoaderInterface     $loader
130
+	 * @param EE_Maintenance_Mode $maintenance_mode
131
+	 * @param EE_Registry         $registry
132
+	 * @param RequestInterface    $request
133
+	 * @param Router $router
134
+	 * @return EE_System
135
+	 */
136
+	public static function instance(
137
+		LoaderInterface $loader = null,
138
+		EE_Maintenance_Mode $maintenance_mode = null,
139
+		EE_Registry $registry = null,
140
+		RequestInterface $request = null,
141
+		Router $router = null
142
+	) {
143
+		// check if class object is instantiated
144
+		if (! self::$_instance instanceof EE_System) {
145
+			self::$_instance = new self($loader, $maintenance_mode, $registry, $request, $router);
146
+		}
147
+		return self::$_instance;
148
+	}
149
+
150
+
151
+	/**
152
+	 * resets the instance and returns it
153
+	 *
154
+	 * @return EE_System
155
+	 */
156
+	public static function reset()
157
+	{
158
+		self::$_instance->_req_type = null;
159
+		// make sure none of the old hooks are left hanging around
160
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
+		// we need to reset the migration manager in order for it to detect DMSs properly
162
+		EE_Data_Migration_Manager::reset();
163
+		self::instance()->detect_activations_or_upgrades();
164
+		self::instance()->perform_activations_upgrades_and_migrations();
165
+		return self::instance();
166
+	}
167
+
168
+
169
+	/**
170
+	 * sets hooks for running rest of system
171
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
+	 * starting EE Addons from any other point may lead to problems
173
+	 *
174
+	 * @param LoaderInterface     $loader
175
+	 * @param EE_Maintenance_Mode $maintenance_mode
176
+	 * @param EE_Registry         $registry
177
+	 * @param RequestInterface    $request
178
+	 * @param Router $router
179
+	 */
180
+	private function __construct(
181
+		LoaderInterface $loader,
182
+		EE_Maintenance_Mode $maintenance_mode,
183
+		EE_Registry $registry,
184
+		RequestInterface $request,
185
+		Router $router
186
+	) {
187
+		$this->registry = $registry;
188
+		$this->loader = $loader;
189
+		$this->request = $request;
190
+		$this->router = $router;
191
+		$this->maintenance_mode = $maintenance_mode;
192
+		do_action('AHEE__EE_System__construct__begin', $this);
193
+		add_action(
194
+			'AHEE__EE_Bootstrap__load_espresso_addons',
195
+			array($this, 'loadCapabilities'),
196
+			5
197
+		);
198
+		add_action(
199
+			'AHEE__EE_Bootstrap__load_espresso_addons',
200
+			array($this, 'loadCommandBus'),
201
+			7
202
+		);
203
+		add_action(
204
+			'AHEE__EE_Bootstrap__load_espresso_addons',
205
+			array($this, 'loadPluginApi'),
206
+			9
207
+		);
208
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
209
+		add_action(
210
+			'AHEE__EE_Bootstrap__load_espresso_addons',
211
+			array($this, 'load_espresso_addons')
212
+		);
213
+		// when an ee addon is activated, we want to call the core hook(s) again
214
+		// because the newly-activated addon didn't get a chance to run at all
215
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
216
+		// detect whether install or upgrade
217
+		add_action(
218
+			'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
219
+			array($this, 'detect_activations_or_upgrades'),
220
+			3
221
+		);
222
+		// load EE_Config, EE_Textdomain, etc
223
+		add_action(
224
+			'AHEE__EE_Bootstrap__load_core_configuration',
225
+			array($this, 'load_core_configuration'),
226
+			5
227
+		);
228
+		// load specifications for matching routes to current request
229
+		add_action(
230
+			'AHEE__EE_Bootstrap__load_core_configuration',
231
+			array($this, 'loadRouteMatchSpecifications')
232
+		);
233
+		// load EE_Config, EE_Textdomain, etc
234
+		add_action(
235
+			'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
236
+			array($this, 'register_shortcodes_modules_and_widgets'),
237
+			7
238
+		);
239
+		// you wanna get going? I wanna get going... let's get going!
240
+		add_action(
241
+			'AHEE__EE_Bootstrap__brew_espresso',
242
+			array($this, 'brew_espresso'),
243
+			9
244
+		);
245
+		// other housekeeping
246
+		// exclude EE critical pages from wp_list_pages
247
+		add_filter(
248
+			'wp_list_pages_excludes',
249
+			array($this, 'remove_pages_from_wp_list_pages'),
250
+			10
251
+		);
252
+		// ALL EE Addons should use the following hook point to attach their initial setup too
253
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
254
+		do_action('AHEE__EE_System__construct__complete', $this);
255
+	}
256
+
257
+
258
+	/**
259
+	 * load and setup EE_Capabilities
260
+	 *
261
+	 * @return void
262
+	 */
263
+	public function loadCapabilities()
264
+	{
265
+		$this->capabilities = $this->loader->getShared('EE_Capabilities');
266
+		add_action(
267
+			'AHEE__EE_Capabilities__init_caps__before_initialization',
268
+			function () {
269
+				LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
270
+			}
271
+		);
272
+	}
273
+
274
+
275
+	/**
276
+	 * create and cache the CommandBus, and also add middleware
277
+	 * The CapChecker middleware requires the use of EE_Capabilities
278
+	 * which is why we need to load the CommandBus after Caps are set up
279
+	 *
280
+	 * @return void
281
+	 */
282
+	public function loadCommandBus()
283
+	{
284
+		$this->loader->getShared(
285
+			'CommandBusInterface',
286
+			array(
287
+				null,
288
+				apply_filters(
289
+					'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
290
+					array(
291
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
292
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
293
+					)
294
+				),
295
+			)
296
+		);
297
+	}
298
+
299
+
300
+	/**
301
+	 * @return void
302
+	 * @throws EE_Error
303
+	 */
304
+	public function loadPluginApi()
305
+	{
306
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
307
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
308
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
309
+		$this->loader->getShared('EE_Request_Handler');
310
+	}
311
+
312
+
313
+	/**
314
+	 * @param string $addon_name
315
+	 * @param string $version_constant
316
+	 * @param string $min_version_required
317
+	 * @param string $load_callback
318
+	 * @param string $plugin_file_constant
319
+	 * @return void
320
+	 */
321
+	private function deactivateIncompatibleAddon(
322
+		$addon_name,
323
+		$version_constant,
324
+		$min_version_required,
325
+		$load_callback,
326
+		$plugin_file_constant
327
+	) {
328
+		if (! defined($version_constant)) {
329
+			return;
330
+		}
331
+		$addon_version = constant($version_constant);
332
+		if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
333
+			remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
334
+			if (! function_exists('deactivate_plugins')) {
335
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
336
+			}
337
+			deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
338
+			unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
339
+			EE_Error::add_error(
340
+				sprintf(
341
+					esc_html__(
342
+						'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
343
+						'event_espresso'
344
+					),
345
+					$addon_name,
346
+					$min_version_required
347
+				),
348
+				__FILE__,
349
+				__FUNCTION__ . "({$addon_name})",
350
+				__LINE__
351
+			);
352
+			EE_Error::get_notices(false, true);
353
+		}
354
+	}
355
+
356
+
357
+	/**
358
+	 * load_espresso_addons
359
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
360
+	 * this is hooked into both:
361
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
362
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
363
+	 *    and the WP 'activate_plugin' hook point
364
+	 *
365
+	 * @access public
366
+	 * @return void
367
+	 */
368
+	public function load_espresso_addons()
369
+	{
370
+		$this->deactivateIncompatibleAddon(
371
+			'Wait Lists',
372
+			'EE_WAIT_LISTS_VERSION',
373
+			'1.0.0.beta.074',
374
+			'load_espresso_wait_lists',
375
+			'EE_WAIT_LISTS_PLUGIN_FILE'
376
+		);
377
+		$this->deactivateIncompatibleAddon(
378
+			'Automated Upcoming Event Notifications',
379
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
380
+			'1.0.0.beta.091',
381
+			'load_espresso_automated_upcoming_event_notification',
382
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
383
+		);
384
+		do_action('AHEE__EE_System__load_espresso_addons');
385
+		// if the WP API basic auth plugin isn't already loaded, load it now.
386
+		// We want it for mobile apps. Just include the entire plugin
387
+		// also, don't load the basic auth when a plugin is getting activated, because
388
+		// it could be the basic auth plugin, and it doesn't check if its methods are already defined
389
+		// and causes a fatal error
390
+		if (($this->request->isWordPressApi() || $this->request->isApi())
391
+			&& ! $this->request->isActivation()
392
+			&& ! function_exists('json_basic_auth_handler')
393
+			&& ! function_exists('json_basic_auth_error')
394
+		) {
395
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth/basic-auth.php';
396
+		}
397
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
398
+	}
399
+
400
+
401
+	/**
402
+	 * detect_activations_or_upgrades
403
+	 * Checks for activation or upgrade of core first;
404
+	 * then also checks if any registered addons have been activated or upgraded
405
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
406
+	 * which runs during the WP 'plugins_loaded' action at priority 3
407
+	 *
408
+	 * @access public
409
+	 * @return void
410
+	 */
411
+	public function detect_activations_or_upgrades()
412
+	{
413
+		// first off: let's make sure to handle core
414
+		$this->detect_if_activation_or_upgrade();
415
+		foreach ($this->registry->addons as $addon) {
416
+			if ($addon instanceof EE_Addon) {
417
+				// detect teh request type for that addon
418
+				$addon->detect_activation_or_upgrade();
419
+			}
420
+		}
421
+	}
422
+
423
+
424
+	/**
425
+	 * detect_if_activation_or_upgrade
426
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
427
+	 * and either setting up the DB or setting up maintenance mode etc.
428
+	 *
429
+	 * @access public
430
+	 * @return void
431
+	 */
432
+	public function detect_if_activation_or_upgrade()
433
+	{
434
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
435
+		// check if db has been updated, or if its a brand-new installation
436
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
437
+		$request_type = $this->detect_req_type($espresso_db_update);
438
+		// EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
439
+		switch ($request_type) {
440
+			case EE_System::req_type_new_activation:
441
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
442
+				$this->_handle_core_version_change($espresso_db_update);
443
+				break;
444
+			case EE_System::req_type_reactivation:
445
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
446
+				$this->_handle_core_version_change($espresso_db_update);
447
+				break;
448
+			case EE_System::req_type_upgrade:
449
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
450
+				// migrations may be required now that we've upgraded
451
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
452
+				$this->_handle_core_version_change($espresso_db_update);
453
+				break;
454
+			case EE_System::req_type_downgrade:
455
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
456
+				// its possible migrations are no longer required
457
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
458
+				$this->_handle_core_version_change($espresso_db_update);
459
+				break;
460
+			case EE_System::req_type_normal:
461
+			default:
462
+				break;
463
+		}
464
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
465
+	}
466
+
467
+
468
+	/**
469
+	 * Updates the list of installed versions and sets hooks for
470
+	 * initializing the database later during the request
471
+	 *
472
+	 * @param array $espresso_db_update
473
+	 */
474
+	private function _handle_core_version_change($espresso_db_update)
475
+	{
476
+		$this->update_list_of_installed_versions($espresso_db_update);
477
+		// get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
478
+		add_action(
479
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
480
+			array($this, 'initialize_db_if_no_migrations_required')
481
+		);
482
+	}
483
+
484
+
485
+	/**
486
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
487
+	 * information about what versions of EE have been installed and activated,
488
+	 * NOT necessarily the state of the database
489
+	 *
490
+	 * @param mixed $espresso_db_update           the value of the WordPress option.
491
+	 *                                            If not supplied, fetches it from the options table
492
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
493
+	 */
494
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
495
+	{
496
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
497
+		if (! $espresso_db_update) {
498
+			$espresso_db_update = get_option('espresso_db_update');
499
+		}
500
+		// check that option is an array
501
+		if (! is_array($espresso_db_update)) {
502
+			// if option is FALSE, then it never existed
503
+			if ($espresso_db_update === false) {
504
+				// make $espresso_db_update an array and save option with autoload OFF
505
+				$espresso_db_update = array();
506
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
507
+			} else {
508
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
509
+				$espresso_db_update = array($espresso_db_update => array());
510
+				update_option('espresso_db_update', $espresso_db_update);
511
+			}
512
+		} else {
513
+			$corrected_db_update = array();
514
+			// if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
515
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
516
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
517
+					// the key is an int, and the value IS NOT an array
518
+					// so it must be numerically-indexed, where values are versions installed...
519
+					// fix it!
520
+					$version_string = $should_be_array;
521
+					$corrected_db_update[ $version_string ] = array('unknown-date');
522
+				} else {
523
+					// ok it checks out
524
+					$corrected_db_update[ $should_be_version_string ] = $should_be_array;
525
+				}
526
+			}
527
+			$espresso_db_update = $corrected_db_update;
528
+			update_option('espresso_db_update', $espresso_db_update);
529
+		}
530
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
531
+		return $espresso_db_update;
532
+	}
533
+
534
+
535
+	/**
536
+	 * Does the traditional work of setting up the plugin's database and adding default data.
537
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
538
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
539
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
540
+	 * so that it will be done when migrations are finished
541
+	 *
542
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
543
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
544
+	 *                                       This is a resource-intensive job
545
+	 *                                       so we prefer to only do it when necessary
546
+	 * @return void
547
+	 * @throws EE_Error
548
+	 */
549
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
550
+	{
551
+		$request_type = $this->detect_req_type();
552
+		// only initialize system if we're not in maintenance mode.
553
+		if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
554
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
555
+			$rewrite_rules = $this->loader->getShared(
556
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
557
+			);
558
+			$rewrite_rules->flush();
559
+			if ($verify_schema) {
560
+				EEH_Activation::initialize_db_and_folders();
561
+			}
562
+			EEH_Activation::initialize_db_content();
563
+			EEH_Activation::system_initialization();
564
+			if ($initialize_addons_too) {
565
+				$this->initialize_addons();
566
+			}
567
+		} else {
568
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
569
+		}
570
+		if ($request_type === EE_System::req_type_new_activation
571
+			|| $request_type === EE_System::req_type_reactivation
572
+			|| (
573
+				$request_type === EE_System::req_type_upgrade
574
+				&& $this->is_major_version_change()
575
+			)
576
+		) {
577
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
578
+		}
579
+	}
580
+
581
+
582
+	/**
583
+	 * Initializes the db for all registered addons
584
+	 *
585
+	 * @throws EE_Error
586
+	 */
587
+	public function initialize_addons()
588
+	{
589
+		// foreach registered addon, make sure its db is up-to-date too
590
+		foreach ($this->registry->addons as $addon) {
591
+			if ($addon instanceof EE_Addon) {
592
+				$addon->initialize_db_if_no_migrations_required();
593
+			}
594
+		}
595
+	}
596
+
597
+
598
+	/**
599
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
600
+	 *
601
+	 * @param    array  $version_history
602
+	 * @param    string $current_version_to_add version to be added to the version history
603
+	 * @return    boolean success as to whether or not this option was changed
604
+	 */
605
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
606
+	{
607
+		if (! $version_history) {
608
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
609
+		}
610
+		if ($current_version_to_add === null) {
611
+			$current_version_to_add = espresso_version();
612
+		}
613
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
614
+		// re-save
615
+		return update_option('espresso_db_update', $version_history);
616
+	}
617
+
618
+
619
+	/**
620
+	 * Detects if the current version indicated in the has existed in the list of
621
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
622
+	 *
623
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
624
+	 *                                  If not supplied, fetches it from the options table.
625
+	 *                                  Also, caches its result so later parts of the code can also know whether
626
+	 *                                  there's been an update or not. This way we can add the current version to
627
+	 *                                  espresso_db_update, but still know if this is a new install or not
628
+	 * @return int one of the constants on EE_System::req_type_
629
+	 */
630
+	public function detect_req_type($espresso_db_update = null)
631
+	{
632
+		if ($this->_req_type === null) {
633
+			$espresso_db_update = ! empty($espresso_db_update)
634
+				? $espresso_db_update
635
+				: $this->fix_espresso_db_upgrade_option();
636
+			$this->_req_type = EE_System::detect_req_type_given_activation_history(
637
+				$espresso_db_update,
638
+				'ee_espresso_activation',
639
+				espresso_version()
640
+			);
641
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
642
+			$this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
643
+		}
644
+		return $this->_req_type;
645
+	}
646
+
647
+
648
+	/**
649
+	 * Returns whether or not there was a non-micro version change (ie, change in either
650
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
651
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
652
+	 *
653
+	 * @param $activation_history
654
+	 * @return bool
655
+	 */
656
+	private function _detect_major_version_change($activation_history)
657
+	{
658
+		$previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
659
+		$previous_version_parts = explode('.', $previous_version);
660
+		$current_version_parts = explode('.', espresso_version());
661
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
662
+			   && (
663
+				   $previous_version_parts[0] !== $current_version_parts[0]
664
+				   || $previous_version_parts[1] !== $current_version_parts[1]
665
+			   );
666
+	}
667
+
668
+
669
+	/**
670
+	 * Returns true if either the major or minor version of EE changed during this request.
671
+	 * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
672
+	 *
673
+	 * @return bool
674
+	 */
675
+	public function is_major_version_change()
676
+	{
677
+		return $this->_major_version_change;
678
+	}
679
+
680
+
681
+	/**
682
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
683
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
684
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
685
+	 * just activated to (for core that will always be espresso_version())
686
+	 *
687
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
688
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
689
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
690
+	 *                                                 indicate that this plugin was just activated
691
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
692
+	 *                                                 espresso_version())
693
+	 * @return int one of the constants on EE_System::req_type_*
694
+	 */
695
+	public static function detect_req_type_given_activation_history(
696
+		$activation_history_for_addon,
697
+		$activation_indicator_option_name,
698
+		$version_to_upgrade_to
699
+	) {
700
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
701
+		if ($activation_history_for_addon) {
702
+			// it exists, so this isn't a completely new install
703
+			// check if this version already in that list of previously installed versions
704
+			if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
705
+				// it a version we haven't seen before
706
+				if ($version_is_higher === 1) {
707
+					$req_type = EE_System::req_type_upgrade;
708
+				} else {
709
+					$req_type = EE_System::req_type_downgrade;
710
+				}
711
+				delete_option($activation_indicator_option_name);
712
+			} else {
713
+				// its not an update. maybe a reactivation?
714
+				if (get_option($activation_indicator_option_name, false)) {
715
+					if ($version_is_higher === -1) {
716
+						$req_type = EE_System::req_type_downgrade;
717
+					} elseif ($version_is_higher === 0) {
718
+						// we've seen this version before, but it's an activation. must be a reactivation
719
+						$req_type = EE_System::req_type_reactivation;
720
+					} else {// $version_is_higher === 1
721
+						$req_type = EE_System::req_type_upgrade;
722
+					}
723
+					delete_option($activation_indicator_option_name);
724
+				} else {
725
+					// we've seen this version before and the activation indicate doesn't show it was just activated
726
+					if ($version_is_higher === -1) {
727
+						$req_type = EE_System::req_type_downgrade;
728
+					} elseif ($version_is_higher === 0) {
729
+						// we've seen this version before and it's not an activation. its normal request
730
+						$req_type = EE_System::req_type_normal;
731
+					} else {// $version_is_higher === 1
732
+						$req_type = EE_System::req_type_upgrade;
733
+					}
734
+				}
735
+			}
736
+		} else {
737
+			// brand new install
738
+			$req_type = EE_System::req_type_new_activation;
739
+			delete_option($activation_indicator_option_name);
740
+		}
741
+		return $req_type;
742
+	}
743
+
744
+
745
+	/**
746
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
747
+	 * the $activation_history_for_addon
748
+	 *
749
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
750
+	 *                                             sometimes containing 'unknown-date'
751
+	 * @param string $version_to_upgrade_to        (current version)
752
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
753
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
754
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
755
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
756
+	 */
757
+	private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
758
+	{
759
+		// find the most recently-activated version
760
+		$most_recently_active_version =
761
+			EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
762
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
763
+	}
764
+
765
+
766
+	/**
767
+	 * Gets the most recently active version listed in the activation history,
768
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
769
+	 *
770
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
771
+	 *                                   sometimes containing 'unknown-date'
772
+	 * @return string
773
+	 */
774
+	private static function _get_most_recently_active_version_from_activation_history($activation_history)
775
+	{
776
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
777
+		$most_recently_active_version = '0.0.0.dev.000';
778
+		if (is_array($activation_history)) {
779
+			foreach ($activation_history as $version => $times_activated) {
780
+				// check there is a record of when this version was activated. Otherwise,
781
+				// mark it as unknown
782
+				if (! $times_activated) {
783
+					$times_activated = array('unknown-date');
784
+				}
785
+				if (is_string($times_activated)) {
786
+					$times_activated = array($times_activated);
787
+				}
788
+				foreach ($times_activated as $an_activation) {
789
+					if ($an_activation !== 'unknown-date'
790
+						&& $an_activation
791
+						   > $most_recently_active_version_activation) {
792
+						$most_recently_active_version = $version;
793
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
794
+							? '1970-01-01 00:00:00'
795
+							: $an_activation;
796
+					}
797
+				}
798
+			}
799
+		}
800
+		return $most_recently_active_version;
801
+	}
802
+
803
+
804
+	/**
805
+	 * This redirects to the about EE page after activation
806
+	 *
807
+	 * @return void
808
+	 */
809
+	public function redirect_to_about_ee()
810
+	{
811
+		$notices = EE_Error::get_notices(false);
812
+		// if current user is an admin and it's not an ajax or rest request
813
+		if (! isset($notices['errors'])
814
+			&& $this->request->isAdmin()
815
+			&& apply_filters(
816
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
817
+				$this->capabilities->current_user_can('manage_options', 'espresso_about_default')
818
+			)
819
+		) {
820
+			$query_params = array('page' => 'espresso_about');
821
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
822
+				$query_params['new_activation'] = true;
823
+			}
824
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
825
+				$query_params['reactivation'] = true;
826
+			}
827
+			$url = add_query_arg($query_params, admin_url('admin.php'));
828
+			wp_safe_redirect($url);
829
+			exit();
830
+		}
831
+	}
832
+
833
+
834
+	/**
835
+	 * load_core_configuration
836
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
837
+	 * which runs during the WP 'plugins_loaded' action at priority 5
838
+	 *
839
+	 * @return void
840
+	 * @throws ReflectionException
841
+	 * @throws Exception
842
+	 */
843
+	public function load_core_configuration()
844
+	{
845
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
846
+		$this->loader->getShared('EE_Load_Textdomain');
847
+		// load textdomain
848
+		EE_Load_Textdomain::load_textdomain();
849
+		// load caf stuff a chance to play during the activation process too.
850
+		$this->_maybe_brew_regular();
851
+		// load and setup EE_Config and EE_Network_Config
852
+		$config = $this->loader->getShared('EE_Config');
853
+		$this->loader->getShared('EE_Network_Config');
854
+		// setup autoloaders
855
+		// enable logging?
856
+		if ($config->admin->use_remote_logging) {
857
+			$this->loader->getShared('EE_Log');
858
+		}
859
+		// check for activation errors
860
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
861
+		if ($activation_errors) {
862
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
863
+			update_option('ee_plugin_activation_errors', false);
864
+		}
865
+		// get model names
866
+		$this->_parse_model_names();
867
+		// configure custom post type definitions
868
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
869
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
870
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
871
+	}
872
+
873
+
874
+	/**
875
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
876
+	 *
877
+	 * @return void
878
+	 * @throws ReflectionException
879
+	 */
880
+	private function _parse_model_names()
881
+	{
882
+		// get all the files in the EE_MODELS folder that end in .model.php
883
+		$models = glob(EE_MODELS . '*.model.php');
884
+		$model_names = array();
885
+		$non_abstract_db_models = array();
886
+		foreach ($models as $model) {
887
+			// get model classname
888
+			$classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
889
+			$short_name = str_replace('EEM_', '', $classname);
890
+			$reflectionClass = new ReflectionClass($classname);
891
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
892
+				$non_abstract_db_models[ $short_name ] = $classname;
893
+			}
894
+			$model_names[ $short_name ] = $classname;
895
+		}
896
+		$this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
897
+		$this->registry->non_abstract_db_models = apply_filters(
898
+			'FHEE__EE_System__parse_implemented_model_names',
899
+			$non_abstract_db_models
900
+		);
901
+	}
902
+
903
+
904
+	/**
905
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
906
+	 * that need to be setup before our EE_System launches.
907
+	 *
908
+	 * @return void
909
+	 * @throws DomainException
910
+	 * @throws InvalidArgumentException
911
+	 * @throws InvalidDataTypeException
912
+	 * @throws InvalidInterfaceException
913
+	 * @throws InvalidClassException
914
+	 * @throws InvalidFilePathException
915
+	 */
916
+	private function _maybe_brew_regular()
917
+	{
918
+		/** @var Domain $domain */
919
+		$domain = DomainFactory::getShared(
920
+			new FullyQualifiedName(
921
+				'EventEspresso\core\domain\Domain'
922
+			),
923
+			array(
924
+				new FilePath(EVENT_ESPRESSO_MAIN_FILE),
925
+				Version::fromString(espresso_version()),
926
+			)
927
+		);
928
+		if ($domain->isCaffeinated()) {
929
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
930
+		}
931
+	}
932
+
933
+
934
+	/**
935
+	 * @since 4.9.71.p
936
+	 * @throws Exception
937
+	 */
938
+	public function loadRouteMatchSpecifications()
939
+	{
940
+		try {
941
+			$this->loader->getShared('EventEspresso\core\services\routing\RouteMatchSpecificationManager');
942
+			$this->loader->getShared('EventEspresso\core\services\routing\RouteCollection');
943
+			$this->router->loadPrimaryRoutes();
944
+		} catch (Exception $exception) {
945
+			new ExceptionStackTraceDisplay($exception);
946
+		}
947
+		do_action('AHEE__EE_System__loadRouteMatchSpecifications');
948
+	}
949
+
950
+
951
+	/**
952
+	 * register_shortcodes_modules_and_widgets
953
+	 * generate lists of shortcodes and modules, then verify paths and classes
954
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
955
+	 * which runs during the WP 'plugins_loaded' action at priority 7
956
+	 *
957
+	 * @access public
958
+	 * @return void
959
+	 * @throws Exception
960
+	 */
961
+	public function register_shortcodes_modules_and_widgets()
962
+	{
963
+		$this->router->registerShortcodesModulesAndWidgets();
964
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
965
+		// check for addons using old hook point
966
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
967
+			$this->_incompatible_addon_error();
968
+		}
969
+	}
970
+
971
+
972
+	/**
973
+	 * _incompatible_addon_error
974
+	 *
975
+	 * @access public
976
+	 * @return void
977
+	 */
978
+	private function _incompatible_addon_error()
979
+	{
980
+		// get array of classes hooking into here
981
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
982
+			'AHEE__EE_System__register_shortcodes_modules_and_addons'
983
+		);
984
+		if (! empty($class_names)) {
985
+			$msg = __(
986
+				'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
987
+				'event_espresso'
988
+			);
989
+			$msg .= '<ul>';
990
+			foreach ($class_names as $class_name) {
991
+				$msg .= '<li><b>Event Espresso - '
992
+						. str_replace(
993
+							array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
994
+							'',
995
+							$class_name
996
+						) . '</b></li>';
997
+			}
998
+			$msg .= '</ul>';
999
+			$msg .= __(
1000
+				'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1001
+				'event_espresso'
1002
+			);
1003
+			// save list of incompatible addons to wp-options for later use
1004
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
1005
+			if (is_admin()) {
1006
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1007
+			}
1008
+		}
1009
+	}
1010
+
1011
+
1012
+	/**
1013
+	 * brew_espresso
1014
+	 * begins the process of setting hooks for initializing EE in the correct order
1015
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1016
+	 * which runs during the WP 'plugins_loaded' action at priority 9
1017
+	 *
1018
+	 * @return void
1019
+	 * @throws Exception
1020
+	 */
1021
+	public function brew_espresso()
1022
+	{
1023
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
1024
+		// load some final core systems
1025
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
1026
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1027
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
1028
+		add_action('init', array($this, 'load_controllers'), 7);
1029
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
1030
+		add_action('init', array($this, 'initialize'), 10);
1031
+		add_action('init', array($this, 'initialize_last'), 100);
1032
+		$this->router->brewEspresso();
1033
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
1034
+	}
1035
+
1036
+
1037
+	/**
1038
+	 *    set_hooks_for_core
1039
+	 *
1040
+	 * @access public
1041
+	 * @return    void
1042
+	 * @throws EE_Error
1043
+	 */
1044
+	public function set_hooks_for_core()
1045
+	{
1046
+		$this->_deactivate_incompatible_addons();
1047
+		do_action('AHEE__EE_System__set_hooks_for_core');
1048
+		$this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1049
+		// caps need to be initialized on every request so that capability maps are set.
1050
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1051
+		$this->registry->CAP->init_caps();
1052
+	}
1053
+
1054
+
1055
+	/**
1056
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
1057
+	 * deactivates any addons considered incompatible with the current version of EE
1058
+	 */
1059
+	private function _deactivate_incompatible_addons()
1060
+	{
1061
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
1062
+		if (! empty($incompatible_addons)) {
1063
+			$active_plugins = get_option('active_plugins', array());
1064
+			foreach ($active_plugins as $active_plugin) {
1065
+				foreach ($incompatible_addons as $incompatible_addon) {
1066
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
1067
+						unset($_GET['activate']);
1068
+						espresso_deactivate_plugin($active_plugin);
1069
+					}
1070
+				}
1071
+			}
1072
+		}
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 *    perform_activations_upgrades_and_migrations
1078
+	 *
1079
+	 * @access public
1080
+	 * @return    void
1081
+	 */
1082
+	public function perform_activations_upgrades_and_migrations()
1083
+	{
1084
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1085
+	}
1086
+
1087
+
1088
+	/**
1089
+	 * @return void
1090
+	 * @throws DomainException
1091
+	 */
1092
+	public function load_CPTs_and_session()
1093
+	{
1094
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
1095
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1096
+		$register_custom_taxonomies = $this->loader->getShared(
1097
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1098
+		);
1099
+		$register_custom_taxonomies->registerCustomTaxonomies();
1100
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1101
+		$register_custom_post_types = $this->loader->getShared(
1102
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1103
+		);
1104
+		$register_custom_post_types->registerCustomPostTypes();
1105
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1106
+		$register_custom_taxonomy_terms = $this->loader->getShared(
1107
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1108
+		);
1109
+		$register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1110
+		// load legacy Custom Post Types and Taxonomies
1111
+		$this->loader->getShared('EE_Register_CPTs');
1112
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1113
+	}
1114
+
1115
+
1116
+	/**
1117
+	 * load_controllers
1118
+	 * this is the best place to load any additional controllers that needs access to EE core.
1119
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1120
+	 * time
1121
+	 *
1122
+	 * @access public
1123
+	 * @return void
1124
+	 * @throws Exception
1125
+	 */
1126
+	public function load_controllers()
1127
+	{
1128
+		do_action('AHEE__EE_System__load_controllers__start');
1129
+		$this->router->loadControllers();
1130
+		do_action('AHEE__EE_System__load_controllers__complete');
1131
+	}
1132
+
1133
+
1134
+	/**
1135
+	 * core_loaded_and_ready
1136
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1137
+	 *
1138
+	 * @access public
1139
+	 * @return void
1140
+	 * @throws Exception
1141
+	 */
1142
+	public function core_loaded_and_ready()
1143
+	{
1144
+		$this->router->coreLoadedAndReady();
1145
+		// integrate WP_Query with the EE models
1146
+		$this->loader->getShared('EE_CPT_Strategy');
1147
+		do_action('AHEE__EE_System__core_loaded_and_ready');
1148
+		// always load template tags, because it's faster than checking if it's a front-end request, and many page
1149
+		// builders require these even on the front-end
1150
+		require_once EE_PUBLIC . 'template_tags.php';
1151
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1152
+	}
1153
+
1154
+
1155
+	/**
1156
+	 * initialize
1157
+	 * this is the best place to begin initializing client code
1158
+	 *
1159
+	 * @access public
1160
+	 * @return void
1161
+	 */
1162
+	public function initialize()
1163
+	{
1164
+		do_action('AHEE__EE_System__initialize');
1165
+	}
1166
+
1167
+
1168
+	/**
1169
+	 * initialize_last
1170
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1171
+	 * initialize has done so
1172
+	 *
1173
+	 * @access public
1174
+	 * @return void
1175
+	 * @throws Exception
1176
+	 */
1177
+	public function initialize_last()
1178
+	{
1179
+		do_action('AHEE__EE_System__initialize_last');
1180
+		/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1181
+		$rewrite_rules = $this->loader->getShared(
1182
+			'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1183
+		);
1184
+		$rewrite_rules->flushRewriteRules();
1185
+		$this->router->initializeLast();
1186
+		add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * @return void
1192
+	 */
1193
+	public function addEspressoToolbar()
1194
+	{
1195
+		$this->loader->getShared(
1196
+			'EventEspresso\core\domain\services\admin\AdminToolBar',
1197
+			array($this->registry->CAP)
1198
+		);
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * do_not_cache
1204
+	 * sets no cache headers and defines no cache constants for WP plugins
1205
+	 *
1206
+	 * @access public
1207
+	 * @return void
1208
+	 */
1209
+	public static function do_not_cache()
1210
+	{
1211
+		// set no cache constants
1212
+		if (! defined('DONOTCACHEPAGE')) {
1213
+			define('DONOTCACHEPAGE', true);
1214
+		}
1215
+		if (! defined('DONOTCACHCEOBJECT')) {
1216
+			define('DONOTCACHCEOBJECT', true);
1217
+		}
1218
+		if (! defined('DONOTCACHEDB')) {
1219
+			define('DONOTCACHEDB', true);
1220
+		}
1221
+		// add no cache headers
1222
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1223
+		// plus a little extra for nginx and Google Chrome
1224
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1225
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1226
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1227
+	}
1228
+
1229
+
1230
+	/**
1231
+	 *    extra_nocache_headers
1232
+	 *
1233
+	 * @access    public
1234
+	 * @param $headers
1235
+	 * @return    array
1236
+	 */
1237
+	public static function extra_nocache_headers($headers)
1238
+	{
1239
+		// for NGINX
1240
+		$headers['X-Accel-Expires'] = 0;
1241
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1242
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1243
+		return $headers;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 *    nocache_headers
1249
+	 *
1250
+	 * @access    public
1251
+	 * @return    void
1252
+	 */
1253
+	public static function nocache_headers()
1254
+	{
1255
+		nocache_headers();
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1261
+	 * never returned with the function.
1262
+	 *
1263
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1264
+	 * @return array
1265
+	 */
1266
+	public function remove_pages_from_wp_list_pages($exclude_array)
1267
+	{
1268
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1269
+	}
1270 1270
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
         Router $router = null
142 142
     ) {
143 143
         // check if class object is instantiated
144
-        if (! self::$_instance instanceof EE_System) {
144
+        if ( ! self::$_instance instanceof EE_System) {
145 145
             self::$_instance = new self($loader, $maintenance_mode, $registry, $request, $router);
146 146
         }
147 147
         return self::$_instance;
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
         $this->capabilities = $this->loader->getShared('EE_Capabilities');
266 266
         add_action(
267 267
             'AHEE__EE_Capabilities__init_caps__before_initialization',
268
-            function () {
268
+            function() {
269 269
                 LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
270 270
             }
271 271
         );
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
     {
306 306
         // set autoloaders for all of the classes implementing EEI_Plugin_API
307 307
         // which provide helpers for EE plugin authors to more easily register certain components with EE.
308
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
308
+        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_LIBRARIES.'plugin_api');
309 309
         $this->loader->getShared('EE_Request_Handler');
310 310
     }
311 311
 
@@ -325,14 +325,14 @@  discard block
 block discarded – undo
325 325
         $load_callback,
326 326
         $plugin_file_constant
327 327
     ) {
328
-        if (! defined($version_constant)) {
328
+        if ( ! defined($version_constant)) {
329 329
             return;
330 330
         }
331 331
         $addon_version = constant($version_constant);
332 332
         if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
333 333
             remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
334
-            if (! function_exists('deactivate_plugins')) {
335
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
334
+            if ( ! function_exists('deactivate_plugins')) {
335
+                require_once ABSPATH.'wp-admin/includes/plugin.php';
336 336
             }
337 337
             deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
338 338
             unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
@@ -346,7 +346,7 @@  discard block
 block discarded – undo
346 346
                     $min_version_required
347 347
                 ),
348 348
                 __FILE__,
349
-                __FUNCTION__ . "({$addon_name})",
349
+                __FUNCTION__."({$addon_name})",
350 350
                 __LINE__
351 351
             );
352 352
             EE_Error::get_notices(false, true);
@@ -392,7 +392,7 @@  discard block
 block discarded – undo
392 392
             && ! function_exists('json_basic_auth_handler')
393 393
             && ! function_exists('json_basic_auth_error')
394 394
         ) {
395
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth/basic-auth.php';
395
+            include_once EE_THIRD_PARTY.'wp-api-basic-auth/basic-auth.php';
396 396
         }
397 397
         do_action('AHEE__EE_System__load_espresso_addons__complete');
398 398
     }
@@ -494,11 +494,11 @@  discard block
 block discarded – undo
494 494
     private function fix_espresso_db_upgrade_option($espresso_db_update = null)
495 495
     {
496 496
         do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
497
-        if (! $espresso_db_update) {
497
+        if ( ! $espresso_db_update) {
498 498
             $espresso_db_update = get_option('espresso_db_update');
499 499
         }
500 500
         // check that option is an array
501
-        if (! is_array($espresso_db_update)) {
501
+        if ( ! is_array($espresso_db_update)) {
502 502
             // if option is FALSE, then it never existed
503 503
             if ($espresso_db_update === false) {
504 504
                 // make $espresso_db_update an array and save option with autoload OFF
@@ -518,10 +518,10 @@  discard block
 block discarded – undo
518 518
                     // so it must be numerically-indexed, where values are versions installed...
519 519
                     // fix it!
520 520
                     $version_string = $should_be_array;
521
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
521
+                    $corrected_db_update[$version_string] = array('unknown-date');
522 522
                 } else {
523 523
                     // ok it checks out
524
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
524
+                    $corrected_db_update[$should_be_version_string] = $should_be_array;
525 525
                 }
526 526
             }
527 527
             $espresso_db_update = $corrected_db_update;
@@ -604,13 +604,13 @@  discard block
 block discarded – undo
604 604
      */
605 605
     public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
606 606
     {
607
-        if (! $version_history) {
607
+        if ( ! $version_history) {
608 608
             $version_history = $this->fix_espresso_db_upgrade_option($version_history);
609 609
         }
610 610
         if ($current_version_to_add === null) {
611 611
             $current_version_to_add = espresso_version();
612 612
         }
613
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
613
+        $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
614 614
         // re-save
615 615
         return update_option('espresso_db_update', $version_history);
616 616
     }
@@ -701,7 +701,7 @@  discard block
 block discarded – undo
701 701
         if ($activation_history_for_addon) {
702 702
             // it exists, so this isn't a completely new install
703 703
             // check if this version already in that list of previously installed versions
704
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
704
+            if ( ! isset($activation_history_for_addon[$version_to_upgrade_to])) {
705 705
                 // it a version we haven't seen before
706 706
                 if ($version_is_higher === 1) {
707 707
                     $req_type = EE_System::req_type_upgrade;
@@ -779,7 +779,7 @@  discard block
 block discarded – undo
779 779
             foreach ($activation_history as $version => $times_activated) {
780 780
                 // check there is a record of when this version was activated. Otherwise,
781 781
                 // mark it as unknown
782
-                if (! $times_activated) {
782
+                if ( ! $times_activated) {
783 783
                     $times_activated = array('unknown-date');
784 784
                 }
785 785
                 if (is_string($times_activated)) {
@@ -810,7 +810,7 @@  discard block
 block discarded – undo
810 810
     {
811 811
         $notices = EE_Error::get_notices(false);
812 812
         // if current user is an admin and it's not an ajax or rest request
813
-        if (! isset($notices['errors'])
813
+        if ( ! isset($notices['errors'])
814 814
             && $this->request->isAdmin()
815 815
             && apply_filters(
816 816
                 'FHEE__EE_System__redirect_to_about_ee__do_redirect',
@@ -880,7 +880,7 @@  discard block
 block discarded – undo
880 880
     private function _parse_model_names()
881 881
     {
882 882
         // get all the files in the EE_MODELS folder that end in .model.php
883
-        $models = glob(EE_MODELS . '*.model.php');
883
+        $models = glob(EE_MODELS.'*.model.php');
884 884
         $model_names = array();
885 885
         $non_abstract_db_models = array();
886 886
         foreach ($models as $model) {
@@ -889,9 +889,9 @@  discard block
 block discarded – undo
889 889
             $short_name = str_replace('EEM_', '', $classname);
890 890
             $reflectionClass = new ReflectionClass($classname);
891 891
             if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
892
-                $non_abstract_db_models[ $short_name ] = $classname;
892
+                $non_abstract_db_models[$short_name] = $classname;
893 893
             }
894
-            $model_names[ $short_name ] = $classname;
894
+            $model_names[$short_name] = $classname;
895 895
         }
896 896
         $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
897 897
         $this->registry->non_abstract_db_models = apply_filters(
@@ -926,7 +926,7 @@  discard block
 block discarded – undo
926 926
             )
927 927
         );
928 928
         if ($domain->isCaffeinated()) {
929
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
929
+            require_once EE_CAFF_PATH.'brewing_regular.php';
930 930
         }
931 931
     }
932 932
 
@@ -981,7 +981,7 @@  discard block
 block discarded – undo
981 981
         $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
982 982
             'AHEE__EE_System__register_shortcodes_modules_and_addons'
983 983
         );
984
-        if (! empty($class_names)) {
984
+        if ( ! empty($class_names)) {
985 985
             $msg = __(
986 986
                 'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
987 987
                 'event_espresso'
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
                             array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
994 994
                             '',
995 995
                             $class_name
996
-                        ) . '</b></li>';
996
+                        ).'</b></li>';
997 997
             }
998 998
             $msg .= '</ul>';
999 999
             $msg .= __(
@@ -1059,7 +1059,7 @@  discard block
 block discarded – undo
1059 1059
     private function _deactivate_incompatible_addons()
1060 1060
     {
1061 1061
         $incompatible_addons = get_option('ee_incompatible_addons', array());
1062
-        if (! empty($incompatible_addons)) {
1062
+        if ( ! empty($incompatible_addons)) {
1063 1063
             $active_plugins = get_option('active_plugins', array());
1064 1064
             foreach ($active_plugins as $active_plugin) {
1065 1065
                 foreach ($incompatible_addons as $incompatible_addon) {
@@ -1147,7 +1147,7 @@  discard block
 block discarded – undo
1147 1147
         do_action('AHEE__EE_System__core_loaded_and_ready');
1148 1148
         // always load template tags, because it's faster than checking if it's a front-end request, and many page
1149 1149
         // builders require these even on the front-end
1150
-        require_once EE_PUBLIC . 'template_tags.php';
1150
+        require_once EE_PUBLIC.'template_tags.php';
1151 1151
         do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1152 1152
     }
1153 1153
 
@@ -1209,13 +1209,13 @@  discard block
 block discarded – undo
1209 1209
     public static function do_not_cache()
1210 1210
     {
1211 1211
         // set no cache constants
1212
-        if (! defined('DONOTCACHEPAGE')) {
1212
+        if ( ! defined('DONOTCACHEPAGE')) {
1213 1213
             define('DONOTCACHEPAGE', true);
1214 1214
         }
1215
-        if (! defined('DONOTCACHCEOBJECT')) {
1215
+        if ( ! defined('DONOTCACHCEOBJECT')) {
1216 1216
             define('DONOTCACHCEOBJECT', true);
1217 1217
         }
1218
-        if (! defined('DONOTCACHEDB')) {
1218
+        if ( ! defined('DONOTCACHEDB')) {
1219 1219
             define('DONOTCACHEDB', true);
1220 1220
         }
1221 1221
         // add no cache headers
Please login to merge, or discard this patch.