Completed
Branch BUG/fix-m-mode-fatal-error (471753)
by
unknown
05:41 queued 03:29
created
core/services/shortcodes/LegacyShortcodesManager.php 1 patch
Indentation   +435 added lines, -435 removed lines patch added patch discarded remove patch
@@ -25,439 +25,439 @@
 block discarded – undo
25 25
  */
26 26
 class LegacyShortcodesManager
27 27
 {
28
-    /**
29
-     * @type CurrentPage
30
-     */
31
-    protected $current_page;
32
-
33
-    /**
34
-     * @var EE_Registry $registry
35
-     */
36
-    private $registry;
37
-
38
-
39
-    /**
40
-     * LegacyShortcodesManager constructor.
41
-     *
42
-     * @param EE_Registry $registry
43
-     * @param CurrentPage $current_page
44
-     */
45
-    public function __construct(EE_Registry $registry, CurrentPage $current_page)
46
-    {
47
-        $this->registry = $registry;
48
-        $this->current_page = $current_page;
49
-    }
50
-
51
-
52
-    /**
53
-     * @return EE_Registry
54
-     */
55
-    public function registry()
56
-    {
57
-        return $this->registry;
58
-    }
59
-
60
-
61
-    /**
62
-     * registerShortcodes
63
-     *
64
-     * @return void
65
-     */
66
-    public function registerShortcodes()
67
-    {
68
-        $this->registry->shortcodes = $this->getShortcodes();
69
-    }
70
-
71
-
72
-    /**
73
-     * getShortcodes
74
-     *
75
-     * @return array
76
-     */
77
-    public function getShortcodes()
78
-    {
79
-        // previously this method would glob the shortcodes directory
80
-        // then filter that list of shortcodes to register,
81
-        // but now we are going to just supply an empty array.
82
-        // this allows any shortcodes that have not yet been converted to the new system
83
-        // to still get loaded and processed, albeit using the same legacy logic as before
84
-        $shortcodes_to_register = apply_filters(
85
-            'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
86
-            array()
87
-        );
88
-        if (! empty($shortcodes_to_register)) {
89
-            // cycle thru shortcode folders
90
-            foreach ($shortcodes_to_register as $shortcode_path) {
91
-                // add to list of installed shortcode modules
92
-                $this->registerShortcode($shortcode_path);
93
-            }
94
-        }
95
-        // filter list of installed modules
96
-        return apply_filters(
97
-            'FHEE__EE_Config___register_shortcodes__installed_shortcodes',
98
-            ! empty($this->registry->shortcodes)
99
-                ? $this->registry->shortcodes
100
-                : array()
101
-        );
102
-    }
103
-
104
-
105
-    /**
106
-     * register_shortcode - makes core aware of this shortcode
107
-     *
108
-     * @param    string $shortcode_path - full path up to and including shortcode folder
109
-     * @return    bool
110
-     */
111
-    public function registerShortcode($shortcode_path = null)
112
-    {
113
-        do_action('AHEE__EE_Config__register_shortcode__begin', $shortcode_path);
114
-        $shortcode_ext = '.shortcode.php';
115
-        // make all separators match
116
-        $shortcode_path = str_replace(array('\\', '/'), '/', $shortcode_path);
117
-        // does the file path INCLUDE the actual file name as part of the path ?
118
-        if (strpos($shortcode_path, $shortcode_ext) !== false) {
119
-            // grab shortcode file name from directory name and break apart at dots
120
-            $shortcode_file = explode('.', basename($shortcode_path));
121
-            // take first segment from file name pieces and remove class prefix if it exists
122
-            $shortcode = strpos($shortcode_file[0], 'EES_') === 0
123
-                ? substr($shortcode_file[0], 4)
124
-                : $shortcode_file[0];
125
-            // sanitize shortcode directory name
126
-            $shortcode = sanitize_key($shortcode);
127
-            // now we need to rebuild the shortcode path
128
-            $shortcode_path = explode('/', $shortcode_path);
129
-            // remove last segment
130
-            array_pop($shortcode_path);
131
-            // glue it back together
132
-            $shortcode_path = implode('/', $shortcode_path) . '/';
133
-        } else {
134
-            // we need to generate the filename based off of the folder name
135
-            // grab and sanitize shortcode directory name
136
-            $shortcode = sanitize_key(basename($shortcode_path));
137
-            $shortcode_path = rtrim($shortcode_path, '/') . '/';
138
-        }
139
-        // create classname from shortcode directory or file name
140
-        $shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
141
-        // add class prefix
142
-        $shortcode_class = 'EES_' . $shortcode;
143
-        // does the shortcode exist ?
144
-        if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
145
-            $msg = sprintf(
146
-                esc_html__(
147
-                    'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
148
-                    'event_espresso'
149
-                ),
150
-                $shortcode_class,
151
-                $shortcode_path . '/' . $shortcode_class . $shortcode_ext
152
-            );
153
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
154
-            return false;
155
-        }
156
-        // load the shortcode class file
157
-        require_once($shortcode_path . $shortcode_class . $shortcode_ext);
158
-        // verify that class exists
159
-        if (! class_exists($shortcode_class)) {
160
-            $msg = sprintf(
161
-                esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
162
-                $shortcode_class
163
-            );
164
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
165
-            return false;
166
-        }
167
-        $shortcode = strtoupper($shortcode);
168
-        // add to array of registered shortcodes
169
-        $this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
170
-        return true;
171
-    }
172
-
173
-
174
-    /**
175
-     *    _initialize_shortcodes
176
-     *    allow shortcodes to set hooks for the rest of the system
177
-     *
178
-     * @return void
179
-     */
180
-    public function addShortcodes()
181
-    {
182
-        // cycle thru shortcode folders
183
-        foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
184
-            // add class prefix
185
-            $shortcode_class = 'EES_' . $shortcode;
186
-            // fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
187
-            // which set hooks ?
188
-            if (is_admin()) {
189
-                // fire immediately
190
-                call_user_func(array($shortcode_class, 'set_hooks_admin'));
191
-            } else {
192
-                // delay until other systems are online
193
-                add_action(
194
-                    'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
195
-                    array($shortcode_class, 'set_hooks')
196
-                );
197
-                // convert classname to UPPERCASE and create WP shortcode.
198
-                $shortcode_tag = strtoupper($shortcode);
199
-                // but first check if the shortcode has already
200
-                // been added before assigning 'fallback_shortcode_processor'
201
-                if (! shortcode_exists($shortcode_tag)) {
202
-                    // NOTE: this shortcode declaration will get overridden if the shortcode
203
-                    // is successfully detected in the post content in initializeShortcode()
204
-                    add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
205
-                }
206
-            }
207
-        }
208
-    }
209
-
210
-
211
-    /**
212
-     * callback for the WP "get_header" hook point
213
-     * checks posts for EE shortcodes, and initializes them,
214
-     * then toggles filter switch that loads core default assets
215
-     *
216
-     * @param WP_Query $wp_query
217
-     * @return void
218
-     * @throws ReflectionException
219
-     */
220
-    public function initializeShortcodes(WP_Query $wp_query)
221
-    {
222
-        if (empty($this->registry->shortcodes) || ! $wp_query->is_main_query() || is_admin()) {
223
-            return;
224
-        }
225
-        // in case shortcode is loaded unexpectedly and deps haven't been set up correctly
226
-        EE_Dependency_Map::register_dependencies(
227
-            'EE_Front_Controller',
228
-            [
229
-                'EE_Registry' => EE_Dependency_Map::load_from_cache,
230
-                'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
231
-                'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
232
-            ]
233
-        );
234
-        global $wp;
235
-        /** @var EE_Front_controller $Front_Controller */
236
-        $Front_Controller = LoaderFactory::getLoader()->getShared('EE_Front_Controller');
237
-        do_action('AHEE__EE_Front_Controller__initialize_shortcodes__begin', $wp, $Front_Controller);
238
-        $this->current_page->parseQueryVars();
239
-        // grab post_name from request
240
-        $current_post = apply_filters(
241
-            'FHEE__EE_Front_Controller__initialize_shortcodes__current_post_name',
242
-            $this->current_page->postName()
243
-        );
244
-        $show_on_front = get_option('show_on_front');
245
-        // if it's not set, then check if frontpage is blog
246
-        if (empty($current_post)) {
247
-            // yup.. this is the posts page, prepare to load all shortcode modules
248
-            $current_post = 'posts';
249
-            // unless..
250
-            if ($show_on_front === 'page') {
251
-                // some other page is set as the homepage
252
-                $page_on_front = get_option('page_on_front');
253
-                if ($page_on_front) {
254
-                    // k now we need to find the post_name for this page
255
-                    global $wpdb;
256
-                    $page_on_front = $wpdb->get_var(
257
-                        $wpdb->prepare(
258
-                            "SELECT post_name from {$wpdb->posts} WHERE post_type='page' AND post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d",
259
-                            $page_on_front
260
-                        )
261
-                    );
262
-                    // set the current post slug to what it actually is
263
-                    $current_post = $page_on_front ?: $current_post;
264
-                }
265
-            }
266
-        }
267
-        // in case $current_post is hierarchical like: /parent-page/current-page
268
-        $current_post = basename($current_post);
269
-        if (
270
-            // is current page/post the "blog" page ?
271
-            $current_post === EE_Config::get_page_for_posts()
272
-            // or are we on a category page?
273
-            || (
274
-                is_array(term_exists($current_post, 'category'))
275
-                || array_key_exists('category_name', $wp->query_vars)
276
-            )
277
-        ) {
278
-            // initialize all legacy shortcodes
279
-            $load_assets = $this->parseContentForShortcodes('', true);
280
-        } else {
281
-            global $post;
282
-            if ($post instanceof WP_Post) {
283
-                $post_content = $post->post_content;
284
-            } else {
285
-                global $wpdb;
286
-                $post_content = $wpdb->get_var(
287
-                    $wpdb->prepare(
288
-                        "SELECT post_content from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s",
289
-                        $current_post
290
-                    )
291
-                );
292
-            }
293
-            $load_assets = $this->parseContentForShortcodes($post_content);
294
-        }
295
-        if ($load_assets) {
296
-            $this->current_page->setEspressoPage(true);
297
-            add_filter('FHEE_load_css', '__return_true');
298
-            add_filter('FHEE_load_js', '__return_true');
299
-        }
300
-        do_action('AHEE__EE_Front_Controller__initialize_shortcodes__end', $Front_Controller);
301
-    }
302
-
303
-
304
-    /**
305
-     * checks supplied content against list of legacy shortcodes,
306
-     * then initializes any found shortcodes, and returns true.
307
-     * returns false if no shortcodes found.
308
-     *
309
-     * @param string $content
310
-     * @param bool   $load_all if true, then ALL active legacy shortcodes will be initialized
311
-     * @return bool
312
-     * @throws ReflectionException
313
-     */
314
-    public function parseContentForShortcodes($content = '', $load_all = false)
315
-    {
316
-        $has_shortcode = false;
317
-        foreach ($this->registry->shortcodes as $shortcode_class => $shortcode) {
318
-            if ($load_all || has_shortcode($content, $shortcode_class)) {
319
-                // load up the shortcode
320
-                $this->initializeShortcode($shortcode_class);
321
-                $has_shortcode = true;
322
-            }
323
-        }
324
-        // one last test for an [espresso_*] shortcode
325
-        if (! $has_shortcode) {
326
-            $has_shortcode = strpos($content, '[espresso_') !== false;
327
-        }
328
-        return $has_shortcode;
329
-    }
330
-
331
-
332
-    /**
333
-     * given a shortcode name, will instantiate the shortcode and call it's run() method
334
-     *
335
-     * @param string $shortcode_class
336
-     * @param WP     $wp
337
-     * @throws ReflectionException
338
-     */
339
-    public function initializeShortcode($shortcode_class = '', WP $wp = null)
340
-    {
341
-        // don't do anything if shortcode is already initialized
342
-        if (
343
-            empty($this->registry->shortcodes->{$shortcode_class})
344
-            || ! is_string($this->registry->shortcodes->{$shortcode_class})
345
-        ) {
346
-            return;
347
-        }
348
-        // let's pause to reflect on this...
349
-        $sc_reflector = new ReflectionClass(LegacyShortcodesManager::addShortcodeClassPrefix($shortcode_class));
350
-        // ensure that class is actually a shortcode
351
-        if (
352
-            defined('WP_DEBUG')
353
-            && WP_DEBUG === true
354
-            && ! $sc_reflector->isSubclassOf('EES_Shortcode')
355
-        ) {
356
-            EE_Error::add_error(
357
-                sprintf(
358
-                    esc_html__(
359
-                        'The requested %s shortcode is not of the class "EES_Shortcode". Please check your files.',
360
-                        'event_espresso'
361
-                    ),
362
-                    $shortcode_class
363
-                ),
364
-                __FILE__,
365
-                __FUNCTION__,
366
-                __LINE__
367
-            );
368
-            add_filter('FHEE_run_EE_the_content', '__return_true');
369
-            return;
370
-        }
371
-        global $wp;
372
-        // and pass the request object to the run method
373
-        $this->registry->shortcodes->{$shortcode_class} = $sc_reflector->newInstance();
374
-        // fire the shortcode class's run method, so that it can activate resources
375
-        $this->registry->shortcodes->{$shortcode_class}->run($wp);
376
-    }
377
-
378
-
379
-    /**
380
-     * get classname, remove EES_prefix, and convert to UPPERCASE
381
-     *
382
-     * @param string $class_name
383
-     * @return string
384
-     */
385
-    public static function generateShortcodeTagFromClassName($class_name)
386
-    {
387
-        return strtoupper(str_replace('EES_', '', $class_name));
388
-    }
389
-
390
-
391
-    /**
392
-     * add EES_prefix and Capitalize words
393
-     *
394
-     * @param string $tag
395
-     * @return string
396
-     */
397
-    public static function generateShortcodeClassNameFromTag($tag)
398
-    {
399
-        // order of operation runs from inside to out
400
-        // 5) maybe add prefix
401
-        return LegacyShortcodesManager::addShortcodeClassPrefix(
402
-            // 4) find spaces, replace with underscores
403
-            str_replace(
404
-                ' ',
405
-                '_',
406
-                // 3) capitalize first letter of each word
407
-                ucwords(
408
-                    // 2) also change to lowercase so ucwords() will work
409
-                    strtolower(
410
-                        // 1) find underscores, replace with spaces so ucwords() will work
411
-                        str_replace(
412
-                            '_',
413
-                            ' ',
414
-                            $tag
415
-                        )
416
-                    )
417
-                )
418
-            )
419
-        );
420
-    }
421
-
422
-
423
-    /**
424
-     * maybe add EES_prefix
425
-     *
426
-     * @param string $class_name
427
-     * @return string
428
-     */
429
-    public static function addShortcodeClassPrefix($class_name)
430
-    {
431
-        return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
432
-    }
433
-
434
-
435
-    /**
436
-     * @return array
437
-     */
438
-    public function getEspressoShortcodeTags()
439
-    {
440
-        static $shortcode_tags = array();
441
-        if (empty($shortcode_tags)) {
442
-            $shortcode_tags = array_keys((array) $this->registry->shortcodes);
443
-        }
444
-        return $shortcode_tags;
445
-    }
446
-
447
-
448
-    /**
449
-     * @param string $content
450
-     * @return string
451
-     * @throws ReflectionException
452
-     */
453
-    public function doShortcode($content)
454
-    {
455
-        foreach ($this->getEspressoShortcodeTags() as $shortcode_tag) {
456
-            if (strpos($content, $shortcode_tag) !== false) {
457
-                $shortcode_class = LegacyShortcodesManager::generateShortcodeClassNameFromTag($shortcode_tag);
458
-                $this->initializeShortcode($shortcode_class);
459
-            }
460
-        }
461
-        return do_shortcode($content);
462
-    }
28
+	/**
29
+	 * @type CurrentPage
30
+	 */
31
+	protected $current_page;
32
+
33
+	/**
34
+	 * @var EE_Registry $registry
35
+	 */
36
+	private $registry;
37
+
38
+
39
+	/**
40
+	 * LegacyShortcodesManager constructor.
41
+	 *
42
+	 * @param EE_Registry $registry
43
+	 * @param CurrentPage $current_page
44
+	 */
45
+	public function __construct(EE_Registry $registry, CurrentPage $current_page)
46
+	{
47
+		$this->registry = $registry;
48
+		$this->current_page = $current_page;
49
+	}
50
+
51
+
52
+	/**
53
+	 * @return EE_Registry
54
+	 */
55
+	public function registry()
56
+	{
57
+		return $this->registry;
58
+	}
59
+
60
+
61
+	/**
62
+	 * registerShortcodes
63
+	 *
64
+	 * @return void
65
+	 */
66
+	public function registerShortcodes()
67
+	{
68
+		$this->registry->shortcodes = $this->getShortcodes();
69
+	}
70
+
71
+
72
+	/**
73
+	 * getShortcodes
74
+	 *
75
+	 * @return array
76
+	 */
77
+	public function getShortcodes()
78
+	{
79
+		// previously this method would glob the shortcodes directory
80
+		// then filter that list of shortcodes to register,
81
+		// but now we are going to just supply an empty array.
82
+		// this allows any shortcodes that have not yet been converted to the new system
83
+		// to still get loaded and processed, albeit using the same legacy logic as before
84
+		$shortcodes_to_register = apply_filters(
85
+			'FHEE__EE_Config__register_shortcodes__shortcodes_to_register',
86
+			array()
87
+		);
88
+		if (! empty($shortcodes_to_register)) {
89
+			// cycle thru shortcode folders
90
+			foreach ($shortcodes_to_register as $shortcode_path) {
91
+				// add to list of installed shortcode modules
92
+				$this->registerShortcode($shortcode_path);
93
+			}
94
+		}
95
+		// filter list of installed modules
96
+		return apply_filters(
97
+			'FHEE__EE_Config___register_shortcodes__installed_shortcodes',
98
+			! empty($this->registry->shortcodes)
99
+				? $this->registry->shortcodes
100
+				: array()
101
+		);
102
+	}
103
+
104
+
105
+	/**
106
+	 * register_shortcode - makes core aware of this shortcode
107
+	 *
108
+	 * @param    string $shortcode_path - full path up to and including shortcode folder
109
+	 * @return    bool
110
+	 */
111
+	public function registerShortcode($shortcode_path = null)
112
+	{
113
+		do_action('AHEE__EE_Config__register_shortcode__begin', $shortcode_path);
114
+		$shortcode_ext = '.shortcode.php';
115
+		// make all separators match
116
+		$shortcode_path = str_replace(array('\\', '/'), '/', $shortcode_path);
117
+		// does the file path INCLUDE the actual file name as part of the path ?
118
+		if (strpos($shortcode_path, $shortcode_ext) !== false) {
119
+			// grab shortcode file name from directory name and break apart at dots
120
+			$shortcode_file = explode('.', basename($shortcode_path));
121
+			// take first segment from file name pieces and remove class prefix if it exists
122
+			$shortcode = strpos($shortcode_file[0], 'EES_') === 0
123
+				? substr($shortcode_file[0], 4)
124
+				: $shortcode_file[0];
125
+			// sanitize shortcode directory name
126
+			$shortcode = sanitize_key($shortcode);
127
+			// now we need to rebuild the shortcode path
128
+			$shortcode_path = explode('/', $shortcode_path);
129
+			// remove last segment
130
+			array_pop($shortcode_path);
131
+			// glue it back together
132
+			$shortcode_path = implode('/', $shortcode_path) . '/';
133
+		} else {
134
+			// we need to generate the filename based off of the folder name
135
+			// grab and sanitize shortcode directory name
136
+			$shortcode = sanitize_key(basename($shortcode_path));
137
+			$shortcode_path = rtrim($shortcode_path, '/') . '/';
138
+		}
139
+		// create classname from shortcode directory or file name
140
+		$shortcode = str_replace(' ', '_', ucwords(str_replace('_', ' ', $shortcode)));
141
+		// add class prefix
142
+		$shortcode_class = 'EES_' . $shortcode;
143
+		// does the shortcode exist ?
144
+		if (! is_readable($shortcode_path . '/' . $shortcode_class . $shortcode_ext)) {
145
+			$msg = sprintf(
146
+				esc_html__(
147
+					'The requested %1$s shortcode file could not be found or is not readable due to file permissions. It should be in %2$s',
148
+					'event_espresso'
149
+				),
150
+				$shortcode_class,
151
+				$shortcode_path . '/' . $shortcode_class . $shortcode_ext
152
+			);
153
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
154
+			return false;
155
+		}
156
+		// load the shortcode class file
157
+		require_once($shortcode_path . $shortcode_class . $shortcode_ext);
158
+		// verify that class exists
159
+		if (! class_exists($shortcode_class)) {
160
+			$msg = sprintf(
161
+				esc_html__('The requested %s shortcode class does not exist.', 'event_espresso'),
162
+				$shortcode_class
163
+			);
164
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
165
+			return false;
166
+		}
167
+		$shortcode = strtoupper($shortcode);
168
+		// add to array of registered shortcodes
169
+		$this->registry->shortcodes->{$shortcode} = $shortcode_path . $shortcode_class . $shortcode_ext;
170
+		return true;
171
+	}
172
+
173
+
174
+	/**
175
+	 *    _initialize_shortcodes
176
+	 *    allow shortcodes to set hooks for the rest of the system
177
+	 *
178
+	 * @return void
179
+	 */
180
+	public function addShortcodes()
181
+	{
182
+		// cycle thru shortcode folders
183
+		foreach ($this->registry->shortcodes as $shortcode => $shortcode_path) {
184
+			// add class prefix
185
+			$shortcode_class = 'EES_' . $shortcode;
186
+			// fire the shortcode class's set_hooks methods in case it needs to hook into other parts of the system
187
+			// which set hooks ?
188
+			if (is_admin()) {
189
+				// fire immediately
190
+				call_user_func(array($shortcode_class, 'set_hooks_admin'));
191
+			} else {
192
+				// delay until other systems are online
193
+				add_action(
194
+					'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons',
195
+					array($shortcode_class, 'set_hooks')
196
+				);
197
+				// convert classname to UPPERCASE and create WP shortcode.
198
+				$shortcode_tag = strtoupper($shortcode);
199
+				// but first check if the shortcode has already
200
+				// been added before assigning 'fallback_shortcode_processor'
201
+				if (! shortcode_exists($shortcode_tag)) {
202
+					// NOTE: this shortcode declaration will get overridden if the shortcode
203
+					// is successfully detected in the post content in initializeShortcode()
204
+					add_shortcode($shortcode_tag, array($shortcode_class, 'fallback_shortcode_processor'));
205
+				}
206
+			}
207
+		}
208
+	}
209
+
210
+
211
+	/**
212
+	 * callback for the WP "get_header" hook point
213
+	 * checks posts for EE shortcodes, and initializes them,
214
+	 * then toggles filter switch that loads core default assets
215
+	 *
216
+	 * @param WP_Query $wp_query
217
+	 * @return void
218
+	 * @throws ReflectionException
219
+	 */
220
+	public function initializeShortcodes(WP_Query $wp_query)
221
+	{
222
+		if (empty($this->registry->shortcodes) || ! $wp_query->is_main_query() || is_admin()) {
223
+			return;
224
+		}
225
+		// in case shortcode is loaded unexpectedly and deps haven't been set up correctly
226
+		EE_Dependency_Map::register_dependencies(
227
+			'EE_Front_Controller',
228
+			[
229
+				'EE_Registry' => EE_Dependency_Map::load_from_cache,
230
+				'EventEspresso\core\services\request\CurrentPage' => EE_Dependency_Map::load_from_cache,
231
+				'EE_Module_Request_Router' => EE_Dependency_Map::load_from_cache,
232
+			]
233
+		);
234
+		global $wp;
235
+		/** @var EE_Front_controller $Front_Controller */
236
+		$Front_Controller = LoaderFactory::getLoader()->getShared('EE_Front_Controller');
237
+		do_action('AHEE__EE_Front_Controller__initialize_shortcodes__begin', $wp, $Front_Controller);
238
+		$this->current_page->parseQueryVars();
239
+		// grab post_name from request
240
+		$current_post = apply_filters(
241
+			'FHEE__EE_Front_Controller__initialize_shortcodes__current_post_name',
242
+			$this->current_page->postName()
243
+		);
244
+		$show_on_front = get_option('show_on_front');
245
+		// if it's not set, then check if frontpage is blog
246
+		if (empty($current_post)) {
247
+			// yup.. this is the posts page, prepare to load all shortcode modules
248
+			$current_post = 'posts';
249
+			// unless..
250
+			if ($show_on_front === 'page') {
251
+				// some other page is set as the homepage
252
+				$page_on_front = get_option('page_on_front');
253
+				if ($page_on_front) {
254
+					// k now we need to find the post_name for this page
255
+					global $wpdb;
256
+					$page_on_front = $wpdb->get_var(
257
+						$wpdb->prepare(
258
+							"SELECT post_name from {$wpdb->posts} WHERE post_type='page' AND post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d",
259
+							$page_on_front
260
+						)
261
+					);
262
+					// set the current post slug to what it actually is
263
+					$current_post = $page_on_front ?: $current_post;
264
+				}
265
+			}
266
+		}
267
+		// in case $current_post is hierarchical like: /parent-page/current-page
268
+		$current_post = basename($current_post);
269
+		if (
270
+			// is current page/post the "blog" page ?
271
+			$current_post === EE_Config::get_page_for_posts()
272
+			// or are we on a category page?
273
+			|| (
274
+				is_array(term_exists($current_post, 'category'))
275
+				|| array_key_exists('category_name', $wp->query_vars)
276
+			)
277
+		) {
278
+			// initialize all legacy shortcodes
279
+			$load_assets = $this->parseContentForShortcodes('', true);
280
+		} else {
281
+			global $post;
282
+			if ($post instanceof WP_Post) {
283
+				$post_content = $post->post_content;
284
+			} else {
285
+				global $wpdb;
286
+				$post_content = $wpdb->get_var(
287
+					$wpdb->prepare(
288
+						"SELECT post_content from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s",
289
+						$current_post
290
+					)
291
+				);
292
+			}
293
+			$load_assets = $this->parseContentForShortcodes($post_content);
294
+		}
295
+		if ($load_assets) {
296
+			$this->current_page->setEspressoPage(true);
297
+			add_filter('FHEE_load_css', '__return_true');
298
+			add_filter('FHEE_load_js', '__return_true');
299
+		}
300
+		do_action('AHEE__EE_Front_Controller__initialize_shortcodes__end', $Front_Controller);
301
+	}
302
+
303
+
304
+	/**
305
+	 * checks supplied content against list of legacy shortcodes,
306
+	 * then initializes any found shortcodes, and returns true.
307
+	 * returns false if no shortcodes found.
308
+	 *
309
+	 * @param string $content
310
+	 * @param bool   $load_all if true, then ALL active legacy shortcodes will be initialized
311
+	 * @return bool
312
+	 * @throws ReflectionException
313
+	 */
314
+	public function parseContentForShortcodes($content = '', $load_all = false)
315
+	{
316
+		$has_shortcode = false;
317
+		foreach ($this->registry->shortcodes as $shortcode_class => $shortcode) {
318
+			if ($load_all || has_shortcode($content, $shortcode_class)) {
319
+				// load up the shortcode
320
+				$this->initializeShortcode($shortcode_class);
321
+				$has_shortcode = true;
322
+			}
323
+		}
324
+		// one last test for an [espresso_*] shortcode
325
+		if (! $has_shortcode) {
326
+			$has_shortcode = strpos($content, '[espresso_') !== false;
327
+		}
328
+		return $has_shortcode;
329
+	}
330
+
331
+
332
+	/**
333
+	 * given a shortcode name, will instantiate the shortcode and call it's run() method
334
+	 *
335
+	 * @param string $shortcode_class
336
+	 * @param WP     $wp
337
+	 * @throws ReflectionException
338
+	 */
339
+	public function initializeShortcode($shortcode_class = '', WP $wp = null)
340
+	{
341
+		// don't do anything if shortcode is already initialized
342
+		if (
343
+			empty($this->registry->shortcodes->{$shortcode_class})
344
+			|| ! is_string($this->registry->shortcodes->{$shortcode_class})
345
+		) {
346
+			return;
347
+		}
348
+		// let's pause to reflect on this...
349
+		$sc_reflector = new ReflectionClass(LegacyShortcodesManager::addShortcodeClassPrefix($shortcode_class));
350
+		// ensure that class is actually a shortcode
351
+		if (
352
+			defined('WP_DEBUG')
353
+			&& WP_DEBUG === true
354
+			&& ! $sc_reflector->isSubclassOf('EES_Shortcode')
355
+		) {
356
+			EE_Error::add_error(
357
+				sprintf(
358
+					esc_html__(
359
+						'The requested %s shortcode is not of the class "EES_Shortcode". Please check your files.',
360
+						'event_espresso'
361
+					),
362
+					$shortcode_class
363
+				),
364
+				__FILE__,
365
+				__FUNCTION__,
366
+				__LINE__
367
+			);
368
+			add_filter('FHEE_run_EE_the_content', '__return_true');
369
+			return;
370
+		}
371
+		global $wp;
372
+		// and pass the request object to the run method
373
+		$this->registry->shortcodes->{$shortcode_class} = $sc_reflector->newInstance();
374
+		// fire the shortcode class's run method, so that it can activate resources
375
+		$this->registry->shortcodes->{$shortcode_class}->run($wp);
376
+	}
377
+
378
+
379
+	/**
380
+	 * get classname, remove EES_prefix, and convert to UPPERCASE
381
+	 *
382
+	 * @param string $class_name
383
+	 * @return string
384
+	 */
385
+	public static function generateShortcodeTagFromClassName($class_name)
386
+	{
387
+		return strtoupper(str_replace('EES_', '', $class_name));
388
+	}
389
+
390
+
391
+	/**
392
+	 * add EES_prefix and Capitalize words
393
+	 *
394
+	 * @param string $tag
395
+	 * @return string
396
+	 */
397
+	public static function generateShortcodeClassNameFromTag($tag)
398
+	{
399
+		// order of operation runs from inside to out
400
+		// 5) maybe add prefix
401
+		return LegacyShortcodesManager::addShortcodeClassPrefix(
402
+			// 4) find spaces, replace with underscores
403
+			str_replace(
404
+				' ',
405
+				'_',
406
+				// 3) capitalize first letter of each word
407
+				ucwords(
408
+					// 2) also change to lowercase so ucwords() will work
409
+					strtolower(
410
+						// 1) find underscores, replace with spaces so ucwords() will work
411
+						str_replace(
412
+							'_',
413
+							' ',
414
+							$tag
415
+						)
416
+					)
417
+				)
418
+			)
419
+		);
420
+	}
421
+
422
+
423
+	/**
424
+	 * maybe add EES_prefix
425
+	 *
426
+	 * @param string $class_name
427
+	 * @return string
428
+	 */
429
+	public static function addShortcodeClassPrefix($class_name)
430
+	{
431
+		return strpos($class_name, 'EES_') === 0 ? $class_name : 'EES_' . $class_name;
432
+	}
433
+
434
+
435
+	/**
436
+	 * @return array
437
+	 */
438
+	public function getEspressoShortcodeTags()
439
+	{
440
+		static $shortcode_tags = array();
441
+		if (empty($shortcode_tags)) {
442
+			$shortcode_tags = array_keys((array) $this->registry->shortcodes);
443
+		}
444
+		return $shortcode_tags;
445
+	}
446
+
447
+
448
+	/**
449
+	 * @param string $content
450
+	 * @return string
451
+	 * @throws ReflectionException
452
+	 */
453
+	public function doShortcode($content)
454
+	{
455
+		foreach ($this->getEspressoShortcodeTags() as $shortcode_tag) {
456
+			if (strpos($content, $shortcode_tag) !== false) {
457
+				$shortcode_class = LegacyShortcodesManager::generateShortcodeClassNameFromTag($shortcode_tag);
458
+				$this->initializeShortcode($shortcode_class);
459
+			}
460
+		}
461
+		return do_shortcode($content);
462
+	}
463 463
 }
Please login to merge, or discard this patch.
core/EE_Registry.core.php 1 patch
Indentation   +1698 added lines, -1698 removed lines patch added patch discarded remove patch
@@ -23,1703 +23,1703 @@
 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
-     * RegistryContainer for storing library classes in
73
-     *
74
-     * @var RegistryContainer $LIB
75
-     */
76
-    public $LIB;
77
-
78
-    /**
79
-     * @var EE_Request_Handler $REQ
80
-     * @deprecated 4.10.14.p
81
-     */
82
-    public $REQ;
83
-
84
-    /**
85
-     * @var EE_Session $SSN
86
-     */
87
-    public $SSN;
88
-
89
-    /**
90
-     * @since 4.5.0
91
-     * @var EE_Capabilities $CAP
92
-     */
93
-    public $CAP;
94
-
95
-    /**
96
-     * @since 4.9.0
97
-     * @var EE_Message_Resource_Manager $MRM
98
-     */
99
-    public $MRM;
100
-
101
-    /**
102
-     * @var Registry $AssetsRegistry
103
-     */
104
-    public $AssetsRegistry;
105
-
106
-    /**
107
-     * RegistryContainer for holding addons which have registered themselves to work with EE core
108
-     *
109
-     * @var RegistryContainer|EE_Addon[] $addons
110
-     */
111
-    public $addons;
112
-
113
-    /**
114
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
115
-     *
116
-     * @var EEM_Base[] $models
117
-     */
118
-    public $models = array();
119
-
120
-    /**
121
-     * @var RegistryContainer|EED_Module[] $modules
122
-     */
123
-    public $modules;
124
-
125
-    /**
126
-     * @var RegistryContainer|EES_Shortcode[] $shortcodes
127
-     */
128
-    public $shortcodes;
129
-
130
-    /**
131
-     * @var RegistryContainer|WP_Widget[] $widgets
132
-     */
133
-    public $widgets;
134
-
135
-    /**
136
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
137
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
138
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
139
-     * classnames (eg "EEM_Event")
140
-     *
141
-     * @var array $non_abstract_db_models
142
-     */
143
-    public $non_abstract_db_models = array();
144
-
145
-    /**
146
-     * internationalization for JS strings
147
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
148
-     *    in js file:  var translatedString = eei18n.string_key;
149
-     *
150
-     * @var array $i18n_js_strings
151
-     */
152
-    public static $i18n_js_strings = array();
153
-
154
-    /**
155
-     * $main_file - path to espresso.php
156
-     *
157
-     * @var array $main_file
158
-     */
159
-    public $main_file;
160
-
161
-    /**
162
-     * array of ReflectionClass objects where the key is the class name
163
-     *
164
-     * @deprecated 4.9.62.p
165
-     * @var ReflectionClass[] $_reflectors
166
-     */
167
-    public $_reflectors;
168
-
169
-    /**
170
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
171
-     *
172
-     * @var boolean $_cache_on
173
-     */
174
-    protected $_cache_on = true;
175
-
176
-    /**
177
-     * @var ObjectIdentifier
178
-     */
179
-    private $object_identifier;
180
-
181
-
182
-    /**
183
-     * @singleton method used to instantiate class object
184
-     * @param EE_Dependency_Map|null   $dependency_map
185
-     * @param Mirror|null              $mirror
186
-     * @param ClassInterfaceCache|null $class_cache
187
-     * @param ObjectIdentifier|null    $object_identifier
188
-     * @return EE_Registry instance
189
-     */
190
-    public static function instance(
191
-        EE_Dependency_Map $dependency_map = null,
192
-        Mirror $mirror = null,
193
-        ClassInterfaceCache $class_cache = null,
194
-        ObjectIdentifier $object_identifier = null
195
-    ) {
196
-        // check if class object is instantiated
197
-        if (
198
-            ! self::$_instance instanceof EE_Registry
199
-            && $dependency_map instanceof EE_Dependency_Map
200
-            && $mirror instanceof Mirror
201
-            && $class_cache instanceof ClassInterfaceCache
202
-            && $object_identifier instanceof ObjectIdentifier
203
-        ) {
204
-            self::$_instance = new self(
205
-                $dependency_map,
206
-                $mirror,
207
-                $class_cache,
208
-                $object_identifier
209
-            );
210
-        }
211
-        return self::$_instance;
212
-    }
213
-
214
-
215
-    /**
216
-     * protected constructor to prevent direct creation
217
-     *
218
-     * @Constructor
219
-     * @param  EE_Dependency_Map  $dependency_map
220
-     * @param Mirror              $mirror
221
-     * @param ClassInterfaceCache $class_cache
222
-     * @param ObjectIdentifier    $object_identifier
223
-     */
224
-    protected function __construct(
225
-        EE_Dependency_Map $dependency_map,
226
-        Mirror $mirror,
227
-        ClassInterfaceCache $class_cache,
228
-        ObjectIdentifier $object_identifier
229
-    ) {
230
-        $this->_dependency_map = $dependency_map;
231
-        $this->mirror = $mirror;
232
-        $this->class_cache = $class_cache;
233
-        $this->object_identifier = $object_identifier;
234
-        // $registry_container = new RegistryContainer();
235
-        $this->LIB = new RegistryContainer();
236
-        $this->addons = new RegistryContainer();
237
-        $this->modules = new RegistryContainer();
238
-        $this->shortcodes = new RegistryContainer();
239
-        $this->widgets = new RegistryContainer();
240
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
241
-    }
242
-
243
-
244
-    /**
245
-     * initialize
246
-     *
247
-     * @throws OutOfBoundsException
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidInterfaceException
250
-     * @throws InvalidDataTypeException
251
-     * @throws EE_Error
252
-     * @throws ReflectionException
253
-     */
254
-    public function initialize()
255
-    {
256
-        $this->_class_abbreviations = apply_filters(
257
-            'FHEE__EE_Registry____construct___class_abbreviations',
258
-            array(
259
-                'EE_Config'                                       => 'CFG',
260
-                'EE_Session'                                      => 'SSN',
261
-                'EE_Capabilities'                                 => 'CAP',
262
-                'EE_Cart'                                         => 'CART',
263
-                'EE_Network_Config'                               => 'NET_CFG',
264
-                'EE_Request_Handler'                              => 'REQ',
265
-                'EE_Message_Resource_Manager'                     => 'MRM',
266
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
267
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
268
-            )
269
-        );
270
-        $this->load_core('Base', array(), true);
271
-        // add our request and response objects to the cache
272
-        $request_loader = $this->_dependency_map->class_loader(
273
-            'EventEspresso\core\services\request\Request'
274
-        );
275
-        $this->_set_cached_class(
276
-            $request_loader(),
277
-            'EventEspresso\core\services\request\Request'
278
-        );
279
-        $response_loader = $this->_dependency_map->class_loader(
280
-            'EventEspresso\core\services\request\Response'
281
-        );
282
-        $this->_set_cached_class(
283
-            $response_loader(),
284
-            'EventEspresso\core\services\request\Response'
285
-        );
286
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
287
-    }
288
-
289
-
290
-    /**
291
-     * @return void
292
-     */
293
-    public function init()
294
-    {
295
-        // Get current page protocol
296
-        $protocol = is_ssl() ? 'https://' : 'http://';
297
-        // Output admin-ajax.php URL with same protocol as current page
298
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
299
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
300
-    }
301
-
302
-
303
-    /**
304
-     * @return array
305
-     */
306
-    public static function sanitize_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
-                $decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
-                $i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
313
-            }
314
-        }
315
-        return $i18n_js_strings;
316
-    }
317
-
318
-
319
-    /**
320
-     * localize_i18n_js_strings
321
-     *
322
-     * @return string
323
-     */
324
-    public static function localize_i18n_js_strings()
325
-    {
326
-        $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
327
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
328
-    }
329
-
330
-
331
-    /**
332
-     * @param mixed string | EED_Module $module
333
-     * @throws OutOfBoundsException
334
-     * @throws InvalidArgumentException
335
-     * @throws InvalidInterfaceException
336
-     * @throws InvalidDataTypeException
337
-     * @throws EE_Error
338
-     * @throws ReflectionException
339
-     */
340
-    public function add_module($module)
341
-    {
342
-        if ($module instanceof EED_Module) {
343
-            $module_class = get_class($module);
344
-            $this->modules->add($module_class, $module);
345
-        } else {
346
-            if (! class_exists('EE_Module_Request_Router', false)) {
347
-                $this->load_core('Module_Request_Router');
348
-            }
349
-            EE_Module_Request_Router::module_factory($module);
350
-        }
351
-    }
352
-
353
-
354
-    /**
355
-     * @param string $module_name
356
-     * @return mixed EED_Module | NULL
357
-     */
358
-    public function get_module($module_name = '')
359
-    {
360
-        return $this->modules->get($module_name);
361
-    }
362
-
363
-
364
-    /**
365
-     * loads core classes - must be singletons
366
-     *
367
-     * @param string $class_name - simple class name ie: session
368
-     * @param mixed  $arguments
369
-     * @param bool   $load_only
370
-     * @return mixed
371
-     * @throws InvalidInterfaceException
372
-     * @throws InvalidDataTypeException
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     * @throws InvalidArgumentException
376
-     */
377
-    public function load_core($class_name, $arguments = array(), $load_only = false)
378
-    {
379
-        $core_paths = apply_filters(
380
-            'FHEE__EE_Registry__load_core__core_paths',
381
-            array(
382
-                EE_CORE,
383
-                EE_ADMIN,
384
-                EE_CPTS,
385
-                EE_CORE . 'CPTs/',
386
-                EE_CORE . 'data_migration_scripts/',
387
-                EE_CORE . 'request_stack/',
388
-                EE_CORE . 'middleware/',
389
-            )
390
-        );
391
-        // retrieve instantiated class
392
-        return $this->_load(
393
-            $core_paths,
394
-            'EE_',
395
-            $class_name,
396
-            'core',
397
-            $arguments,
398
-            false,
399
-            true,
400
-            $load_only
401
-        );
402
-    }
403
-
404
-
405
-    /**
406
-     * loads service classes
407
-     *
408
-     * @param string $class_name - simple class name ie: session
409
-     * @param mixed  $arguments
410
-     * @param bool   $load_only
411
-     * @return mixed
412
-     * @throws InvalidInterfaceException
413
-     * @throws InvalidDataTypeException
414
-     * @throws EE_Error
415
-     * @throws ReflectionException
416
-     * @throws InvalidArgumentException
417
-     */
418
-    public function load_service($class_name, $arguments = array(), $load_only = false)
419
-    {
420
-        $service_paths = apply_filters(
421
-            'FHEE__EE_Registry__load_service__service_paths',
422
-            array(
423
-                EE_CORE . 'services/',
424
-            )
425
-        );
426
-        // retrieve instantiated class
427
-        return $this->_load(
428
-            $service_paths,
429
-            'EE_',
430
-            $class_name,
431
-            'class',
432
-            $arguments,
433
-            false,
434
-            true,
435
-            $load_only
436
-        );
437
-    }
438
-
439
-
440
-    /**
441
-     * loads data_migration_scripts
442
-     *
443
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
444
-     * @param mixed  $arguments
445
-     * @return EE_Data_Migration_Script_Base|mixed
446
-     * @throws InvalidInterfaceException
447
-     * @throws InvalidDataTypeException
448
-     * @throws EE_Error
449
-     * @throws ReflectionException
450
-     * @throws InvalidArgumentException
451
-     */
452
-    public function load_dms($class_name, $arguments = array())
453
-    {
454
-        // retrieve instantiated class
455
-        return $this->_load(
456
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
457
-            'EE_DMS_',
458
-            $class_name,
459
-            'dms',
460
-            $arguments,
461
-            false,
462
-            false
463
-        );
464
-    }
465
-
466
-
467
-    /**
468
-     * loads object creating classes - must be singletons
469
-     *
470
-     * @param string $class_name - simple class name ie: attendee
471
-     * @param mixed  $arguments  - an array of arguments to pass to the class
472
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
473
-     *                           instantiate
474
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
475
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
476
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
477
-     *                           (default)
478
-     * @return EE_Base_Class | bool
479
-     * @throws InvalidInterfaceException
480
-     * @throws InvalidDataTypeException
481
-     * @throws EE_Error
482
-     * @throws ReflectionException
483
-     * @throws InvalidArgumentException
484
-     */
485
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
486
-    {
487
-        $paths = apply_filters(
488
-            'FHEE__EE_Registry__load_class__paths',
489
-            array(
490
-                EE_CORE,
491
-                EE_CLASSES,
492
-                EE_BUSINESS,
493
-            )
494
-        );
495
-        // retrieve instantiated class
496
-        return $this->_load(
497
-            $paths,
498
-            'EE_',
499
-            $class_name,
500
-            'class',
501
-            $arguments,
502
-            $from_db,
503
-            $cache,
504
-            $load_only
505
-        );
506
-    }
507
-
508
-
509
-    /**
510
-     * loads helper classes - must be singletons
511
-     *
512
-     * @param string $class_name - simple class name ie: price
513
-     * @param mixed  $arguments
514
-     * @param bool   $load_only
515
-     * @return EEH_Base | bool
516
-     * @throws InvalidInterfaceException
517
-     * @throws InvalidDataTypeException
518
-     * @throws EE_Error
519
-     * @throws ReflectionException
520
-     * @throws InvalidArgumentException
521
-     */
522
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
523
-    {
524
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
525
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
526
-        // retrieve instantiated class
527
-        return $this->_load(
528
-            $helper_paths,
529
-            'EEH_',
530
-            $class_name,
531
-            'helper',
532
-            $arguments,
533
-            false,
534
-            true,
535
-            $load_only
536
-        );
537
-    }
538
-
539
-
540
-    /**
541
-     * loads core classes - must be singletons
542
-     *
543
-     * @param string $class_name - simple class name ie: session
544
-     * @param mixed  $arguments
545
-     * @param bool   $load_only
546
-     * @param bool   $cache      whether to cache the object or not.
547
-     * @return mixed
548
-     * @throws InvalidInterfaceException
549
-     * @throws InvalidDataTypeException
550
-     * @throws EE_Error
551
-     * @throws ReflectionException
552
-     * @throws InvalidArgumentException
553
-     */
554
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
555
-    {
556
-        $paths = array(
557
-            EE_LIBRARIES,
558
-            EE_LIBRARIES . 'messages/',
559
-            EE_LIBRARIES . 'shortcodes/',
560
-            EE_LIBRARIES . 'qtips/',
561
-            EE_LIBRARIES . 'payment_methods/',
562
-        );
563
-        // retrieve instantiated class
564
-        return $this->_load(
565
-            $paths,
566
-            'EE_',
567
-            $class_name,
568
-            'lib',
569
-            $arguments,
570
-            false,
571
-            $cache,
572
-            $load_only
573
-        );
574
-    }
575
-
576
-
577
-    /**
578
-     * loads model classes - must be singletons
579
-     *
580
-     * @param string $class_name - simple class name ie: price
581
-     * @param mixed  $arguments
582
-     * @param bool   $load_only
583
-     * @return EEM_Base | bool
584
-     * @throws InvalidInterfaceException
585
-     * @throws InvalidDataTypeException
586
-     * @throws EE_Error
587
-     * @throws ReflectionException
588
-     * @throws InvalidArgumentException
589
-     */
590
-    public function load_model($class_name, $arguments = array(), $load_only = false)
591
-    {
592
-        $paths = apply_filters(
593
-            'FHEE__EE_Registry__load_model__paths',
594
-            array(
595
-                EE_MODELS,
596
-                EE_CORE,
597
-            )
598
-        );
599
-        // retrieve instantiated class
600
-        return $this->_load(
601
-            $paths,
602
-            'EEM_',
603
-            $class_name,
604
-            'model',
605
-            $arguments,
606
-            false,
607
-            true,
608
-            $load_only
609
-        );
610
-    }
611
-
612
-
613
-    /**
614
-     * loads model classes - must be singletons
615
-     *
616
-     * @param string $class_name - simple class name ie: price
617
-     * @param mixed  $arguments
618
-     * @param bool   $load_only
619
-     * @return mixed | bool
620
-     * @throws InvalidInterfaceException
621
-     * @throws InvalidDataTypeException
622
-     * @throws EE_Error
623
-     * @throws ReflectionException
624
-     * @throws InvalidArgumentException
625
-     */
626
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
627
-    {
628
-        $paths = array(
629
-            EE_MODELS . 'fields/',
630
-            EE_MODELS . 'helpers/',
631
-            EE_MODELS . 'relations/',
632
-            EE_MODELS . 'strategies/',
633
-        );
634
-        // retrieve instantiated class
635
-        return $this->_load(
636
-            $paths,
637
-            'EE_',
638
-            $class_name,
639
-            '',
640
-            $arguments,
641
-            false,
642
-            true,
643
-            $load_only
644
-        );
645
-    }
646
-
647
-
648
-    /**
649
-     * Determines if $model_name is the name of an actual EE model.
650
-     *
651
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
652
-     * @return boolean
653
-     */
654
-    public function is_model_name($model_name)
655
-    {
656
-        return isset($this->models[ $model_name ]);
657
-    }
658
-
659
-
660
-    /**
661
-     * generic class loader
662
-     *
663
-     * @param string $path_to_file - directory path to file location, not including filename
664
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
665
-     * @param string $type         - file type - core? class? helper? model?
666
-     * @param mixed  $arguments
667
-     * @param bool   $load_only
668
-     * @return mixed
669
-     * @throws InvalidInterfaceException
670
-     * @throws InvalidDataTypeException
671
-     * @throws EE_Error
672
-     * @throws ReflectionException
673
-     * @throws InvalidArgumentException
674
-     */
675
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
676
-    {
677
-        // retrieve instantiated class
678
-        return $this->_load(
679
-            $path_to_file,
680
-            '',
681
-            $file_name,
682
-            $type,
683
-            $arguments,
684
-            false,
685
-            true,
686
-            $load_only
687
-        );
688
-    }
689
-
690
-
691
-    /**
692
-     * @param string $path_to_file - directory path to file location, not including filename
693
-     * @param string $class_name   - full class name  ie:  My_Class
694
-     * @param string $type         - file type - core? class? helper? model?
695
-     * @param mixed  $arguments
696
-     * @param bool   $load_only
697
-     * @return bool|EE_Addon|object
698
-     * @throws InvalidInterfaceException
699
-     * @throws InvalidDataTypeException
700
-     * @throws EE_Error
701
-     * @throws ReflectionException
702
-     * @throws InvalidArgumentException
703
-     */
704
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
705
-    {
706
-        // retrieve instantiated class
707
-        return $this->_load(
708
-            $path_to_file,
709
-            'addon',
710
-            $class_name,
711
-            $type,
712
-            $arguments,
713
-            false,
714
-            true,
715
-            $load_only
716
-        );
717
-    }
718
-
719
-
720
-    /**
721
-     * instantiates, caches, and automatically resolves dependencies
722
-     * for classes that use a Fully Qualified Class Name.
723
-     * if the class is not capable of being loaded using PSR-4 autoloading,
724
-     * then you need to use one of the existing load_*() methods
725
-     * which can resolve the classname and filepath from the passed arguments
726
-     *
727
-     * @param bool|string $class_name   Fully Qualified Class Name
728
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
729
-     * @param bool        $cache        whether to cache the instantiated object for reuse
730
-     * @param bool        $from_db      some classes are instantiated from the db
731
-     *                                  and thus call a different method to instantiate
732
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
733
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
734
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
735
-     *                                  object = class loaded and instantiated successfully.
736
-     *                                  bool = fail or success when $load_only is true
737
-     * @throws InvalidInterfaceException
738
-     * @throws InvalidDataTypeException
739
-     * @throws EE_Error
740
-     * @throws ReflectionException
741
-     * @throws InvalidArgumentException
742
-     */
743
-    public function create(
744
-        $class_name = false,
745
-        $arguments = array(),
746
-        $cache = false,
747
-        $from_db = false,
748
-        $load_only = false,
749
-        $addon = false
750
-    ) {
751
-        $class_name = ltrim($class_name, '\\');
752
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
753
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
754
-        // if a non-FQCN was passed, then
755
-        // verifyClassExists() might return an object
756
-        // or it could return null if the class just could not be found anywhere
757
-        if ($class_exists instanceof $class_name || $class_exists === null) {
758
-            // either way, return the results
759
-            return $class_exists;
760
-        }
761
-        $class_name = $class_exists;
762
-        // if we're only loading the class and it already exists, then let's just return true immediately
763
-        if ($load_only) {
764
-            return true;
765
-        }
766
-        $addon = $addon ? 'addon' : '';
767
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
768
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
769
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
770
-        if ($this->_cache_on && $cache && ! $load_only) {
771
-            // return object if it's already cached
772
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
773
-            if ($cached_class !== null) {
774
-                return $cached_class;
775
-            }
776
-        }// obtain the loader method from the dependency map
777
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
778
-        if ($loader instanceof Closure) {
779
-            $class_obj = $loader($arguments);
780
-        } else {
781
-            if ($loader && method_exists($this, $loader)) {
782
-                $class_obj = $this->{$loader}($class_name, $arguments);
783
-            } else {
784
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
785
-            }
786
-        }
787
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
788
-            // save it for later... kinda like gum  { : $
789
-            $this->_set_cached_class(
790
-                $class_obj,
791
-                $class_name,
792
-                $addon,
793
-                $from_db,
794
-                $arguments
795
-            );
796
-        }
797
-        $this->_cache_on = true;
798
-        return $class_obj;
799
-    }
800
-
801
-
802
-    /**
803
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
804
-     *
805
-     * @param string|object $class_name
806
-     * @param array         $arguments
807
-     * @param int           $attempt
808
-     * @return mixed
809
-     */
810
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
811
-    {
812
-        if (is_object($class_name) || class_exists($class_name)) {
813
-            return $class_name;
814
-        }
815
-        switch ($attempt) {
816
-            case 1:
817
-                // if it's a FQCN then maybe the class is registered with a preceding \
818
-                $class_name = strpos($class_name, '\\') !== false
819
-                    ? '\\' . ltrim($class_name, '\\')
820
-                    : $class_name;
821
-                break;
822
-            case 2:
823
-                //
824
-                $loader = $this->_dependency_map->class_loader($class_name);
825
-                if ($loader && method_exists($this, $loader)) {
826
-                    return $this->{$loader}($class_name, $arguments);
827
-                }
828
-                break;
829
-            case 3:
830
-            default:
831
-                return null;
832
-        }
833
-        $attempt++;
834
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
835
-    }
836
-
837
-
838
-    /**
839
-     * instantiates, caches, and injects dependencies for classes
840
-     *
841
-     * @param array       $file_paths   an array of paths to folders to look in
842
-     * @param string      $class_prefix EE  or EEM or... ???
843
-     * @param bool|string $class_name   $class name
844
-     * @param string      $type         file type - core? class? helper? model?
845
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
846
-     * @param bool        $from_db      some classes are instantiated from the db
847
-     *                                  and thus call a different method to instantiate
848
-     * @param bool        $cache        whether to cache the instantiated object for reuse
849
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
850
-     * @return bool|null|object null = failure to load or instantiate class object.
851
-     *                                  object = class loaded and instantiated successfully.
852
-     *                                  bool = fail or success when $load_only is true
853
-     * @throws EE_Error
854
-     * @throws ReflectionException
855
-     * @throws InvalidInterfaceException
856
-     * @throws InvalidDataTypeException
857
-     * @throws InvalidArgumentException
858
-     */
859
-    protected function _load(
860
-        $file_paths = array(),
861
-        $class_prefix = 'EE_',
862
-        $class_name = false,
863
-        $type = 'class',
864
-        $arguments = array(),
865
-        $from_db = false,
866
-        $cache = true,
867
-        $load_only = false
868
-    ) {
869
-        $class_name = ltrim($class_name, '\\');
870
-        // strip php file extension
871
-        $class_name = str_replace('.php', '', trim($class_name));
872
-        // does the class have a prefix ?
873
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
874
-            // make sure $class_prefix is uppercase
875
-            $class_prefix = strtoupper(trim($class_prefix));
876
-            // add class prefix ONCE!!!
877
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
878
-        }
879
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
880
-        $class_exists = class_exists($class_name, false);
881
-        // if we're only loading the class and it already exists, then let's just return true immediately
882
-        if ($load_only && $class_exists) {
883
-            return true;
884
-        }
885
-        $arguments = is_array($arguments) ? $arguments : array($arguments);
886
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
887
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
888
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
889
-        if ($this->_cache_on && $cache && ! $load_only) {
890
-            // return object if it's already cached
891
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
892
-            if ($cached_class !== null) {
893
-                return $cached_class;
894
-            }
895
-        }
896
-        // if the class doesn't already exist.. then we need to try and find the file and load it
897
-        if (! $class_exists) {
898
-            // get full path to file
899
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
900
-            // load the file
901
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
902
-            // if we are only loading a file but NOT instantiating an object
903
-            // then return boolean for whether class was loaded or not
904
-            if ($load_only) {
905
-                return $loaded;
906
-            }
907
-            // if an object was expected but loading failed, then return nothing
908
-            if (! $loaded) {
909
-                return null;
910
-            }
911
-        }
912
-        // instantiate the requested object
913
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
914
-        if ($this->_cache_on && $cache) {
915
-            // save it for later... kinda like gum  { : $
916
-            $this->_set_cached_class(
917
-                $class_obj,
918
-                $class_name,
919
-                $class_prefix,
920
-                $from_db,
921
-                $arguments
922
-            );
923
-        }
924
-        $this->_cache_on = true;
925
-        return $class_obj;
926
-    }
927
-
928
-
929
-    /**
930
-     * @param string $class_name
931
-     * @param string $default have to specify something, but not anything that will conflict
932
-     * @return mixed|string
933
-     */
934
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
935
-    {
936
-        return isset($this->_class_abbreviations[ $class_name ])
937
-            ? $this->_class_abbreviations[ $class_name ]
938
-            : $default;
939
-    }
940
-
941
-
942
-    /**
943
-     * attempts to find a cached version of the requested class
944
-     * by looking in the following places:
945
-     *        $this->{$class_abbreviation}            ie:    $this->CART
946
-     *        $this->{$class_name}                        ie:    $this->Some_Class
947
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
948
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
949
-     *
950
-     * @param string $class_name
951
-     * @param string $class_prefix
952
-     * @param array  $arguments
953
-     * @return mixed
954
-     */
955
-    protected function _get_cached_class(
956
-        $class_name,
957
-        $class_prefix = '',
958
-        $arguments = array()
959
-    ) {
960
-        if ($class_name === 'EE_Registry') {
961
-            return $this;
962
-        }
963
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
964
-        // check if class has already been loaded, and return it if it has been
965
-        if (isset($this->{$class_abbreviation})) {
966
-            return $this->{$class_abbreviation};
967
-        }
968
-        $class_name = str_replace('\\', '_', $class_name);
969
-        if (isset($this->{$class_name})) {
970
-            return $this->{$class_name};
971
-        }
972
-        if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
973
-            return $this->addons->get($class_name);
974
-        }
975
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
976
-        if ($this->LIB->has($object_identifier)) {
977
-            return $this->LIB->get($object_identifier);
978
-        }
979
-        foreach ($this->LIB as $key => $object) {
980
-            if (
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
+	 * RegistryContainer for storing library classes in
73
+	 *
74
+	 * @var RegistryContainer $LIB
75
+	 */
76
+	public $LIB;
77
+
78
+	/**
79
+	 * @var EE_Request_Handler $REQ
80
+	 * @deprecated 4.10.14.p
81
+	 */
82
+	public $REQ;
83
+
84
+	/**
85
+	 * @var EE_Session $SSN
86
+	 */
87
+	public $SSN;
88
+
89
+	/**
90
+	 * @since 4.5.0
91
+	 * @var EE_Capabilities $CAP
92
+	 */
93
+	public $CAP;
94
+
95
+	/**
96
+	 * @since 4.9.0
97
+	 * @var EE_Message_Resource_Manager $MRM
98
+	 */
99
+	public $MRM;
100
+
101
+	/**
102
+	 * @var Registry $AssetsRegistry
103
+	 */
104
+	public $AssetsRegistry;
105
+
106
+	/**
107
+	 * RegistryContainer for holding addons which have registered themselves to work with EE core
108
+	 *
109
+	 * @var RegistryContainer|EE_Addon[] $addons
110
+	 */
111
+	public $addons;
112
+
113
+	/**
114
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
115
+	 *
116
+	 * @var EEM_Base[] $models
117
+	 */
118
+	public $models = array();
119
+
120
+	/**
121
+	 * @var RegistryContainer|EED_Module[] $modules
122
+	 */
123
+	public $modules;
124
+
125
+	/**
126
+	 * @var RegistryContainer|EES_Shortcode[] $shortcodes
127
+	 */
128
+	public $shortcodes;
129
+
130
+	/**
131
+	 * @var RegistryContainer|WP_Widget[] $widgets
132
+	 */
133
+	public $widgets;
134
+
135
+	/**
136
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
137
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
138
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
139
+	 * classnames (eg "EEM_Event")
140
+	 *
141
+	 * @var array $non_abstract_db_models
142
+	 */
143
+	public $non_abstract_db_models = array();
144
+
145
+	/**
146
+	 * internationalization for JS strings
147
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
148
+	 *    in js file:  var translatedString = eei18n.string_key;
149
+	 *
150
+	 * @var array $i18n_js_strings
151
+	 */
152
+	public static $i18n_js_strings = array();
153
+
154
+	/**
155
+	 * $main_file - path to espresso.php
156
+	 *
157
+	 * @var array $main_file
158
+	 */
159
+	public $main_file;
160
+
161
+	/**
162
+	 * array of ReflectionClass objects where the key is the class name
163
+	 *
164
+	 * @deprecated 4.9.62.p
165
+	 * @var ReflectionClass[] $_reflectors
166
+	 */
167
+	public $_reflectors;
168
+
169
+	/**
170
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
171
+	 *
172
+	 * @var boolean $_cache_on
173
+	 */
174
+	protected $_cache_on = true;
175
+
176
+	/**
177
+	 * @var ObjectIdentifier
178
+	 */
179
+	private $object_identifier;
180
+
181
+
182
+	/**
183
+	 * @singleton method used to instantiate class object
184
+	 * @param EE_Dependency_Map|null   $dependency_map
185
+	 * @param Mirror|null              $mirror
186
+	 * @param ClassInterfaceCache|null $class_cache
187
+	 * @param ObjectIdentifier|null    $object_identifier
188
+	 * @return EE_Registry instance
189
+	 */
190
+	public static function instance(
191
+		EE_Dependency_Map $dependency_map = null,
192
+		Mirror $mirror = null,
193
+		ClassInterfaceCache $class_cache = null,
194
+		ObjectIdentifier $object_identifier = null
195
+	) {
196
+		// check if class object is instantiated
197
+		if (
198
+			! self::$_instance instanceof EE_Registry
199
+			&& $dependency_map instanceof EE_Dependency_Map
200
+			&& $mirror instanceof Mirror
201
+			&& $class_cache instanceof ClassInterfaceCache
202
+			&& $object_identifier instanceof ObjectIdentifier
203
+		) {
204
+			self::$_instance = new self(
205
+				$dependency_map,
206
+				$mirror,
207
+				$class_cache,
208
+				$object_identifier
209
+			);
210
+		}
211
+		return self::$_instance;
212
+	}
213
+
214
+
215
+	/**
216
+	 * protected constructor to prevent direct creation
217
+	 *
218
+	 * @Constructor
219
+	 * @param  EE_Dependency_Map  $dependency_map
220
+	 * @param Mirror              $mirror
221
+	 * @param ClassInterfaceCache $class_cache
222
+	 * @param ObjectIdentifier    $object_identifier
223
+	 */
224
+	protected function __construct(
225
+		EE_Dependency_Map $dependency_map,
226
+		Mirror $mirror,
227
+		ClassInterfaceCache $class_cache,
228
+		ObjectIdentifier $object_identifier
229
+	) {
230
+		$this->_dependency_map = $dependency_map;
231
+		$this->mirror = $mirror;
232
+		$this->class_cache = $class_cache;
233
+		$this->object_identifier = $object_identifier;
234
+		// $registry_container = new RegistryContainer();
235
+		$this->LIB = new RegistryContainer();
236
+		$this->addons = new RegistryContainer();
237
+		$this->modules = new RegistryContainer();
238
+		$this->shortcodes = new RegistryContainer();
239
+		$this->widgets = new RegistryContainer();
240
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
241
+	}
242
+
243
+
244
+	/**
245
+	 * initialize
246
+	 *
247
+	 * @throws OutOfBoundsException
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidInterfaceException
250
+	 * @throws InvalidDataTypeException
251
+	 * @throws EE_Error
252
+	 * @throws ReflectionException
253
+	 */
254
+	public function initialize()
255
+	{
256
+		$this->_class_abbreviations = apply_filters(
257
+			'FHEE__EE_Registry____construct___class_abbreviations',
258
+			array(
259
+				'EE_Config'                                       => 'CFG',
260
+				'EE_Session'                                      => 'SSN',
261
+				'EE_Capabilities'                                 => 'CAP',
262
+				'EE_Cart'                                         => 'CART',
263
+				'EE_Network_Config'                               => 'NET_CFG',
264
+				'EE_Request_Handler'                              => 'REQ',
265
+				'EE_Message_Resource_Manager'                     => 'MRM',
266
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
267
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
268
+			)
269
+		);
270
+		$this->load_core('Base', array(), true);
271
+		// add our request and response objects to the cache
272
+		$request_loader = $this->_dependency_map->class_loader(
273
+			'EventEspresso\core\services\request\Request'
274
+		);
275
+		$this->_set_cached_class(
276
+			$request_loader(),
277
+			'EventEspresso\core\services\request\Request'
278
+		);
279
+		$response_loader = $this->_dependency_map->class_loader(
280
+			'EventEspresso\core\services\request\Response'
281
+		);
282
+		$this->_set_cached_class(
283
+			$response_loader(),
284
+			'EventEspresso\core\services\request\Response'
285
+		);
286
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
287
+	}
288
+
289
+
290
+	/**
291
+	 * @return void
292
+	 */
293
+	public function init()
294
+	{
295
+		// Get current page protocol
296
+		$protocol = is_ssl() ? 'https://' : 'http://';
297
+		// Output admin-ajax.php URL with same protocol as current page
298
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
299
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
300
+	}
301
+
302
+
303
+	/**
304
+	 * @return array
305
+	 */
306
+	public static function sanitize_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
+				$decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
+				$i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
313
+			}
314
+		}
315
+		return $i18n_js_strings;
316
+	}
317
+
318
+
319
+	/**
320
+	 * localize_i18n_js_strings
321
+	 *
322
+	 * @return string
323
+	 */
324
+	public static function localize_i18n_js_strings()
325
+	{
326
+		$i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
327
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
328
+	}
329
+
330
+
331
+	/**
332
+	 * @param mixed string | EED_Module $module
333
+	 * @throws OutOfBoundsException
334
+	 * @throws InvalidArgumentException
335
+	 * @throws InvalidInterfaceException
336
+	 * @throws InvalidDataTypeException
337
+	 * @throws EE_Error
338
+	 * @throws ReflectionException
339
+	 */
340
+	public function add_module($module)
341
+	{
342
+		if ($module instanceof EED_Module) {
343
+			$module_class = get_class($module);
344
+			$this->modules->add($module_class, $module);
345
+		} else {
346
+			if (! class_exists('EE_Module_Request_Router', false)) {
347
+				$this->load_core('Module_Request_Router');
348
+			}
349
+			EE_Module_Request_Router::module_factory($module);
350
+		}
351
+	}
352
+
353
+
354
+	/**
355
+	 * @param string $module_name
356
+	 * @return mixed EED_Module | NULL
357
+	 */
358
+	public function get_module($module_name = '')
359
+	{
360
+		return $this->modules->get($module_name);
361
+	}
362
+
363
+
364
+	/**
365
+	 * loads core classes - must be singletons
366
+	 *
367
+	 * @param string $class_name - simple class name ie: session
368
+	 * @param mixed  $arguments
369
+	 * @param bool   $load_only
370
+	 * @return mixed
371
+	 * @throws InvalidInterfaceException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 * @throws InvalidArgumentException
376
+	 */
377
+	public function load_core($class_name, $arguments = array(), $load_only = false)
378
+	{
379
+		$core_paths = apply_filters(
380
+			'FHEE__EE_Registry__load_core__core_paths',
381
+			array(
382
+				EE_CORE,
383
+				EE_ADMIN,
384
+				EE_CPTS,
385
+				EE_CORE . 'CPTs/',
386
+				EE_CORE . 'data_migration_scripts/',
387
+				EE_CORE . 'request_stack/',
388
+				EE_CORE . 'middleware/',
389
+			)
390
+		);
391
+		// retrieve instantiated class
392
+		return $this->_load(
393
+			$core_paths,
394
+			'EE_',
395
+			$class_name,
396
+			'core',
397
+			$arguments,
398
+			false,
399
+			true,
400
+			$load_only
401
+		);
402
+	}
403
+
404
+
405
+	/**
406
+	 * loads service classes
407
+	 *
408
+	 * @param string $class_name - simple class name ie: session
409
+	 * @param mixed  $arguments
410
+	 * @param bool   $load_only
411
+	 * @return mixed
412
+	 * @throws InvalidInterfaceException
413
+	 * @throws InvalidDataTypeException
414
+	 * @throws EE_Error
415
+	 * @throws ReflectionException
416
+	 * @throws InvalidArgumentException
417
+	 */
418
+	public function load_service($class_name, $arguments = array(), $load_only = false)
419
+	{
420
+		$service_paths = apply_filters(
421
+			'FHEE__EE_Registry__load_service__service_paths',
422
+			array(
423
+				EE_CORE . 'services/',
424
+			)
425
+		);
426
+		// retrieve instantiated class
427
+		return $this->_load(
428
+			$service_paths,
429
+			'EE_',
430
+			$class_name,
431
+			'class',
432
+			$arguments,
433
+			false,
434
+			true,
435
+			$load_only
436
+		);
437
+	}
438
+
439
+
440
+	/**
441
+	 * loads data_migration_scripts
442
+	 *
443
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
444
+	 * @param mixed  $arguments
445
+	 * @return EE_Data_Migration_Script_Base|mixed
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws EE_Error
449
+	 * @throws ReflectionException
450
+	 * @throws InvalidArgumentException
451
+	 */
452
+	public function load_dms($class_name, $arguments = array())
453
+	{
454
+		// retrieve instantiated class
455
+		return $this->_load(
456
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
457
+			'EE_DMS_',
458
+			$class_name,
459
+			'dms',
460
+			$arguments,
461
+			false,
462
+			false
463
+		);
464
+	}
465
+
466
+
467
+	/**
468
+	 * loads object creating classes - must be singletons
469
+	 *
470
+	 * @param string $class_name - simple class name ie: attendee
471
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
472
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
473
+	 *                           instantiate
474
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
475
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
476
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
477
+	 *                           (default)
478
+	 * @return EE_Base_Class | bool
479
+	 * @throws InvalidInterfaceException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws EE_Error
482
+	 * @throws ReflectionException
483
+	 * @throws InvalidArgumentException
484
+	 */
485
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
486
+	{
487
+		$paths = apply_filters(
488
+			'FHEE__EE_Registry__load_class__paths',
489
+			array(
490
+				EE_CORE,
491
+				EE_CLASSES,
492
+				EE_BUSINESS,
493
+			)
494
+		);
495
+		// retrieve instantiated class
496
+		return $this->_load(
497
+			$paths,
498
+			'EE_',
499
+			$class_name,
500
+			'class',
501
+			$arguments,
502
+			$from_db,
503
+			$cache,
504
+			$load_only
505
+		);
506
+	}
507
+
508
+
509
+	/**
510
+	 * loads helper classes - must be singletons
511
+	 *
512
+	 * @param string $class_name - simple class name ie: price
513
+	 * @param mixed  $arguments
514
+	 * @param bool   $load_only
515
+	 * @return EEH_Base | bool
516
+	 * @throws InvalidInterfaceException
517
+	 * @throws InvalidDataTypeException
518
+	 * @throws EE_Error
519
+	 * @throws ReflectionException
520
+	 * @throws InvalidArgumentException
521
+	 */
522
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
523
+	{
524
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
525
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
526
+		// retrieve instantiated class
527
+		return $this->_load(
528
+			$helper_paths,
529
+			'EEH_',
530
+			$class_name,
531
+			'helper',
532
+			$arguments,
533
+			false,
534
+			true,
535
+			$load_only
536
+		);
537
+	}
538
+
539
+
540
+	/**
541
+	 * loads core classes - must be singletons
542
+	 *
543
+	 * @param string $class_name - simple class name ie: session
544
+	 * @param mixed  $arguments
545
+	 * @param bool   $load_only
546
+	 * @param bool   $cache      whether to cache the object or not.
547
+	 * @return mixed
548
+	 * @throws InvalidInterfaceException
549
+	 * @throws InvalidDataTypeException
550
+	 * @throws EE_Error
551
+	 * @throws ReflectionException
552
+	 * @throws InvalidArgumentException
553
+	 */
554
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
555
+	{
556
+		$paths = array(
557
+			EE_LIBRARIES,
558
+			EE_LIBRARIES . 'messages/',
559
+			EE_LIBRARIES . 'shortcodes/',
560
+			EE_LIBRARIES . 'qtips/',
561
+			EE_LIBRARIES . 'payment_methods/',
562
+		);
563
+		// retrieve instantiated class
564
+		return $this->_load(
565
+			$paths,
566
+			'EE_',
567
+			$class_name,
568
+			'lib',
569
+			$arguments,
570
+			false,
571
+			$cache,
572
+			$load_only
573
+		);
574
+	}
575
+
576
+
577
+	/**
578
+	 * loads model classes - must be singletons
579
+	 *
580
+	 * @param string $class_name - simple class name ie: price
581
+	 * @param mixed  $arguments
582
+	 * @param bool   $load_only
583
+	 * @return EEM_Base | bool
584
+	 * @throws InvalidInterfaceException
585
+	 * @throws InvalidDataTypeException
586
+	 * @throws EE_Error
587
+	 * @throws ReflectionException
588
+	 * @throws InvalidArgumentException
589
+	 */
590
+	public function load_model($class_name, $arguments = array(), $load_only = false)
591
+	{
592
+		$paths = apply_filters(
593
+			'FHEE__EE_Registry__load_model__paths',
594
+			array(
595
+				EE_MODELS,
596
+				EE_CORE,
597
+			)
598
+		);
599
+		// retrieve instantiated class
600
+		return $this->_load(
601
+			$paths,
602
+			'EEM_',
603
+			$class_name,
604
+			'model',
605
+			$arguments,
606
+			false,
607
+			true,
608
+			$load_only
609
+		);
610
+	}
611
+
612
+
613
+	/**
614
+	 * loads model classes - must be singletons
615
+	 *
616
+	 * @param string $class_name - simple class name ie: price
617
+	 * @param mixed  $arguments
618
+	 * @param bool   $load_only
619
+	 * @return mixed | bool
620
+	 * @throws InvalidInterfaceException
621
+	 * @throws InvalidDataTypeException
622
+	 * @throws EE_Error
623
+	 * @throws ReflectionException
624
+	 * @throws InvalidArgumentException
625
+	 */
626
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
627
+	{
628
+		$paths = array(
629
+			EE_MODELS . 'fields/',
630
+			EE_MODELS . 'helpers/',
631
+			EE_MODELS . 'relations/',
632
+			EE_MODELS . 'strategies/',
633
+		);
634
+		// retrieve instantiated class
635
+		return $this->_load(
636
+			$paths,
637
+			'EE_',
638
+			$class_name,
639
+			'',
640
+			$arguments,
641
+			false,
642
+			true,
643
+			$load_only
644
+		);
645
+	}
646
+
647
+
648
+	/**
649
+	 * Determines if $model_name is the name of an actual EE model.
650
+	 *
651
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
652
+	 * @return boolean
653
+	 */
654
+	public function is_model_name($model_name)
655
+	{
656
+		return isset($this->models[ $model_name ]);
657
+	}
658
+
659
+
660
+	/**
661
+	 * generic class loader
662
+	 *
663
+	 * @param string $path_to_file - directory path to file location, not including filename
664
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
665
+	 * @param string $type         - file type - core? class? helper? model?
666
+	 * @param mixed  $arguments
667
+	 * @param bool   $load_only
668
+	 * @return mixed
669
+	 * @throws InvalidInterfaceException
670
+	 * @throws InvalidDataTypeException
671
+	 * @throws EE_Error
672
+	 * @throws ReflectionException
673
+	 * @throws InvalidArgumentException
674
+	 */
675
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
676
+	{
677
+		// retrieve instantiated class
678
+		return $this->_load(
679
+			$path_to_file,
680
+			'',
681
+			$file_name,
682
+			$type,
683
+			$arguments,
684
+			false,
685
+			true,
686
+			$load_only
687
+		);
688
+	}
689
+
690
+
691
+	/**
692
+	 * @param string $path_to_file - directory path to file location, not including filename
693
+	 * @param string $class_name   - full class name  ie:  My_Class
694
+	 * @param string $type         - file type - core? class? helper? model?
695
+	 * @param mixed  $arguments
696
+	 * @param bool   $load_only
697
+	 * @return bool|EE_Addon|object
698
+	 * @throws InvalidInterfaceException
699
+	 * @throws InvalidDataTypeException
700
+	 * @throws EE_Error
701
+	 * @throws ReflectionException
702
+	 * @throws InvalidArgumentException
703
+	 */
704
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
705
+	{
706
+		// retrieve instantiated class
707
+		return $this->_load(
708
+			$path_to_file,
709
+			'addon',
710
+			$class_name,
711
+			$type,
712
+			$arguments,
713
+			false,
714
+			true,
715
+			$load_only
716
+		);
717
+	}
718
+
719
+
720
+	/**
721
+	 * instantiates, caches, and automatically resolves dependencies
722
+	 * for classes that use a Fully Qualified Class Name.
723
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
724
+	 * then you need to use one of the existing load_*() methods
725
+	 * which can resolve the classname and filepath from the passed arguments
726
+	 *
727
+	 * @param bool|string $class_name   Fully Qualified Class Name
728
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
729
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
730
+	 * @param bool        $from_db      some classes are instantiated from the db
731
+	 *                                  and thus call a different method to instantiate
732
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
733
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
734
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
735
+	 *                                  object = class loaded and instantiated successfully.
736
+	 *                                  bool = fail or success when $load_only is true
737
+	 * @throws InvalidInterfaceException
738
+	 * @throws InvalidDataTypeException
739
+	 * @throws EE_Error
740
+	 * @throws ReflectionException
741
+	 * @throws InvalidArgumentException
742
+	 */
743
+	public function create(
744
+		$class_name = false,
745
+		$arguments = array(),
746
+		$cache = false,
747
+		$from_db = false,
748
+		$load_only = false,
749
+		$addon = false
750
+	) {
751
+		$class_name = ltrim($class_name, '\\');
752
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
753
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
754
+		// if a non-FQCN was passed, then
755
+		// verifyClassExists() might return an object
756
+		// or it could return null if the class just could not be found anywhere
757
+		if ($class_exists instanceof $class_name || $class_exists === null) {
758
+			// either way, return the results
759
+			return $class_exists;
760
+		}
761
+		$class_name = $class_exists;
762
+		// if we're only loading the class and it already exists, then let's just return true immediately
763
+		if ($load_only) {
764
+			return true;
765
+		}
766
+		$addon = $addon ? 'addon' : '';
767
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
768
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
769
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
770
+		if ($this->_cache_on && $cache && ! $load_only) {
771
+			// return object if it's already cached
772
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
773
+			if ($cached_class !== null) {
774
+				return $cached_class;
775
+			}
776
+		}// obtain the loader method from the dependency map
777
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
778
+		if ($loader instanceof Closure) {
779
+			$class_obj = $loader($arguments);
780
+		} else {
781
+			if ($loader && method_exists($this, $loader)) {
782
+				$class_obj = $this->{$loader}($class_name, $arguments);
783
+			} else {
784
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
785
+			}
786
+		}
787
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
788
+			// save it for later... kinda like gum  { : $
789
+			$this->_set_cached_class(
790
+				$class_obj,
791
+				$class_name,
792
+				$addon,
793
+				$from_db,
794
+				$arguments
795
+			);
796
+		}
797
+		$this->_cache_on = true;
798
+		return $class_obj;
799
+	}
800
+
801
+
802
+	/**
803
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
804
+	 *
805
+	 * @param string|object $class_name
806
+	 * @param array         $arguments
807
+	 * @param int           $attempt
808
+	 * @return mixed
809
+	 */
810
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
811
+	{
812
+		if (is_object($class_name) || class_exists($class_name)) {
813
+			return $class_name;
814
+		}
815
+		switch ($attempt) {
816
+			case 1:
817
+				// if it's a FQCN then maybe the class is registered with a preceding \
818
+				$class_name = strpos($class_name, '\\') !== false
819
+					? '\\' . ltrim($class_name, '\\')
820
+					: $class_name;
821
+				break;
822
+			case 2:
823
+				//
824
+				$loader = $this->_dependency_map->class_loader($class_name);
825
+				if ($loader && method_exists($this, $loader)) {
826
+					return $this->{$loader}($class_name, $arguments);
827
+				}
828
+				break;
829
+			case 3:
830
+			default:
831
+				return null;
832
+		}
833
+		$attempt++;
834
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
835
+	}
836
+
837
+
838
+	/**
839
+	 * instantiates, caches, and injects dependencies for classes
840
+	 *
841
+	 * @param array       $file_paths   an array of paths to folders to look in
842
+	 * @param string      $class_prefix EE  or EEM or... ???
843
+	 * @param bool|string $class_name   $class name
844
+	 * @param string      $type         file type - core? class? helper? model?
845
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
846
+	 * @param bool        $from_db      some classes are instantiated from the db
847
+	 *                                  and thus call a different method to instantiate
848
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
849
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
850
+	 * @return bool|null|object null = failure to load or instantiate class object.
851
+	 *                                  object = class loaded and instantiated successfully.
852
+	 *                                  bool = fail or success when $load_only is true
853
+	 * @throws EE_Error
854
+	 * @throws ReflectionException
855
+	 * @throws InvalidInterfaceException
856
+	 * @throws InvalidDataTypeException
857
+	 * @throws InvalidArgumentException
858
+	 */
859
+	protected function _load(
860
+		$file_paths = array(),
861
+		$class_prefix = 'EE_',
862
+		$class_name = false,
863
+		$type = 'class',
864
+		$arguments = array(),
865
+		$from_db = false,
866
+		$cache = true,
867
+		$load_only = false
868
+	) {
869
+		$class_name = ltrim($class_name, '\\');
870
+		// strip php file extension
871
+		$class_name = str_replace('.php', '', trim($class_name));
872
+		// does the class have a prefix ?
873
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
874
+			// make sure $class_prefix is uppercase
875
+			$class_prefix = strtoupper(trim($class_prefix));
876
+			// add class prefix ONCE!!!
877
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
878
+		}
879
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
880
+		$class_exists = class_exists($class_name, false);
881
+		// if we're only loading the class and it already exists, then let's just return true immediately
882
+		if ($load_only && $class_exists) {
883
+			return true;
884
+		}
885
+		$arguments = is_array($arguments) ? $arguments : array($arguments);
886
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
887
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
888
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
889
+		if ($this->_cache_on && $cache && ! $load_only) {
890
+			// return object if it's already cached
891
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
892
+			if ($cached_class !== null) {
893
+				return $cached_class;
894
+			}
895
+		}
896
+		// if the class doesn't already exist.. then we need to try and find the file and load it
897
+		if (! $class_exists) {
898
+			// get full path to file
899
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
900
+			// load the file
901
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
902
+			// if we are only loading a file but NOT instantiating an object
903
+			// then return boolean for whether class was loaded or not
904
+			if ($load_only) {
905
+				return $loaded;
906
+			}
907
+			// if an object was expected but loading failed, then return nothing
908
+			if (! $loaded) {
909
+				return null;
910
+			}
911
+		}
912
+		// instantiate the requested object
913
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
914
+		if ($this->_cache_on && $cache) {
915
+			// save it for later... kinda like gum  { : $
916
+			$this->_set_cached_class(
917
+				$class_obj,
918
+				$class_name,
919
+				$class_prefix,
920
+				$from_db,
921
+				$arguments
922
+			);
923
+		}
924
+		$this->_cache_on = true;
925
+		return $class_obj;
926
+	}
927
+
928
+
929
+	/**
930
+	 * @param string $class_name
931
+	 * @param string $default have to specify something, but not anything that will conflict
932
+	 * @return mixed|string
933
+	 */
934
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
935
+	{
936
+		return isset($this->_class_abbreviations[ $class_name ])
937
+			? $this->_class_abbreviations[ $class_name ]
938
+			: $default;
939
+	}
940
+
941
+
942
+	/**
943
+	 * attempts to find a cached version of the requested class
944
+	 * by looking in the following places:
945
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
946
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
947
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
948
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
949
+	 *
950
+	 * @param string $class_name
951
+	 * @param string $class_prefix
952
+	 * @param array  $arguments
953
+	 * @return mixed
954
+	 */
955
+	protected function _get_cached_class(
956
+		$class_name,
957
+		$class_prefix = '',
958
+		$arguments = array()
959
+	) {
960
+		if ($class_name === 'EE_Registry') {
961
+			return $this;
962
+		}
963
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
964
+		// check if class has already been loaded, and return it if it has been
965
+		if (isset($this->{$class_abbreviation})) {
966
+			return $this->{$class_abbreviation};
967
+		}
968
+		$class_name = str_replace('\\', '_', $class_name);
969
+		if (isset($this->{$class_name})) {
970
+			return $this->{$class_name};
971
+		}
972
+		if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
973
+			return $this->addons->get($class_name);
974
+		}
975
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
976
+		if ($this->LIB->has($object_identifier)) {
977
+			return $this->LIB->get($object_identifier);
978
+		}
979
+		foreach ($this->LIB as $key => $object) {
980
+			if (
981 981
 // request does not contain new arguments and therefore no args identifier
982
-                ! $this->object_identifier->hasArguments($object_identifier)
983
-                // but previously cached class with args was found
984
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
985
-            ) {
986
-                return $object;
987
-            }
988
-        }
989
-        return null;
990
-    }
991
-
992
-
993
-    /**
994
-     * removes a cached version of the requested class
995
-     *
996
-     * @param string  $class_name
997
-     * @param boolean $addon
998
-     * @param array   $arguments
999
-     * @return boolean
1000
-     */
1001
-    public function clear_cached_class(
1002
-        $class_name,
1003
-        $addon = false,
1004
-        $arguments = array()
1005
-    ) {
1006
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
1007
-        // check if class has already been loaded, and return it if it has been
1008
-        if (isset($this->{$class_abbreviation})) {
1009
-            $this->{$class_abbreviation} = null;
1010
-            return true;
1011
-        }
1012
-        $class_name = str_replace('\\', '_', $class_name);
1013
-        if (isset($this->{$class_name})) {
1014
-            $this->{$class_name} = null;
1015
-            return true;
1016
-        }
1017
-        if ($addon && $this->addons->has($class_name)) {
1018
-            $this->addons->remove($class_name);
1019
-            return true;
1020
-        }
1021
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1022
-        if ($this->LIB->has($class_name)) {
1023
-            $this->LIB->remove($class_name);
1024
-            return true;
1025
-        }
1026
-        return false;
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * _set_cached_class
1032
-     * attempts to cache the instantiated class locally
1033
-     * in one of the following places, in the following order:
1034
-     *        $this->{class_abbreviation}   ie:    $this->CART
1035
-     *        $this->{$class_name}          ie:    $this->Some_Class
1036
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1037
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1038
-     *
1039
-     * @param object $class_obj
1040
-     * @param string $class_name
1041
-     * @param string $class_prefix
1042
-     * @param bool   $from_db
1043
-     * @param array  $arguments
1044
-     * @return void
1045
-     */
1046
-    protected function _set_cached_class(
1047
-        $class_obj,
1048
-        $class_name,
1049
-        $class_prefix = '',
1050
-        $from_db = false,
1051
-        $arguments = array()
1052
-    ) {
1053
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1054
-            return;
1055
-        }
1056
-        // return newly instantiated class
1057
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1058
-        if ($class_abbreviation) {
1059
-            $this->{$class_abbreviation} = $class_obj;
1060
-            return;
1061
-        }
1062
-        $class_name = str_replace('\\', '_', $class_name);
1063
-        if (property_exists($this, $class_name)) {
1064
-            $this->{$class_name} = $class_obj;
1065
-            return;
1066
-        }
1067
-        if ($class_prefix === 'addon') {
1068
-            $this->addons->add($class_name, $class_obj);
1069
-            return;
1070
-        }
1071
-        if (! $from_db) {
1072
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1073
-            $this->LIB->add($class_name, $class_obj);
1074
-        }
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * attempts to find a full valid filepath for the requested class.
1080
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1081
-     * then returns that path if the target file has been found and is readable
1082
-     *
1083
-     * @param string $class_name
1084
-     * @param string $type
1085
-     * @param array  $file_paths
1086
-     * @return string | bool
1087
-     */
1088
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
1089
-    {
1090
-        // make sure $file_paths is an array
1091
-        $file_paths = is_array($file_paths)
1092
-            ? $file_paths
1093
-            : array($file_paths);
1094
-        // cycle thru paths
1095
-        foreach ($file_paths as $key => $file_path) {
1096
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1097
-            $file_path = $file_path
1098
-                ? str_replace(array('/', '\\'), '/', $file_path)
1099
-                : EE_CLASSES;
1100
-            // prep file type
1101
-            $type = ! empty($type)
1102
-                ? trim($type, '.') . '.'
1103
-                : '';
1104
-            // build full file path
1105
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1106
-            // does the file exist and can be read ?
1107
-            if (is_readable($file_paths[ $key ])) {
1108
-                return $file_paths[ $key ];
1109
-            }
1110
-        }
1111
-        return false;
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * basically just performs a require_once()
1117
-     * but with some error handling
1118
-     *
1119
-     * @param  string $path
1120
-     * @param  string $class_name
1121
-     * @param  string $type
1122
-     * @param  array  $file_paths
1123
-     * @return bool
1124
-     * @throws EE_Error
1125
-     * @throws ReflectionException
1126
-     */
1127
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1128
-    {
1129
-        $this->resolve_legacy_class_parent($class_name);
1130
-        // don't give up! you gotta...
1131
-        try {
1132
-            // does the file exist and can it be read ?
1133
-            if (! $path) {
1134
-                // just in case the file has already been autoloaded,
1135
-                // but discrepancies in the naming schema are preventing it from
1136
-                // being loaded via one of the EE_Registry::load_*() methods,
1137
-                // then let's try one last hail mary before throwing an exception
1138
-                // and call class_exists() again, but with autoloading turned ON
1139
-                if (class_exists($class_name)) {
1140
-                    return true;
1141
-                }
1142
-                // so sorry, can't find the file
1143
-                throw new EE_Error(
1144
-                    sprintf(
1145
-                        esc_html__(
1146
-                            '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',
1147
-                            'event_espresso'
1148
-                        ),
1149
-                        trim($type, '.'),
1150
-                        $class_name,
1151
-                        '<br />' . implode(',<br />', $file_paths)
1152
-                    )
1153
-                );
1154
-            }
1155
-            // get the file
1156
-            require_once($path);
1157
-            // if the class isn't already declared somewhere
1158
-            if (class_exists($class_name, false) === false) {
1159
-                // so sorry, not a class
1160
-                throw new EE_Error(
1161
-                    sprintf(
1162
-                        esc_html__(
1163
-                            'The %s file %s does not appear to contain the %s Class.',
1164
-                            'event_espresso'
1165
-                        ),
1166
-                        $type,
1167
-                        $path,
1168
-                        $class_name
1169
-                    )
1170
-                );
1171
-            }
1172
-        } catch (EE_Error $e) {
1173
-            $e->get_error();
1174
-            return false;
1175
-        }
1176
-        return true;
1177
-    }
1178
-
1179
-
1180
-    /**
1181
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1182
-     * before their class declaration in order to ensure that the parent class was loaded.
1183
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1184
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1185
-     *
1186
-     * @param string $class_name
1187
-     */
1188
-    protected function resolve_legacy_class_parent($class_name = '')
1189
-    {
1190
-        try {
1191
-            $legacy_parent_class_map = array(
1192
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1193
-            );
1194
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1195
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1196
-            }
1197
-        } catch (Exception $exception) {
1198
-        }
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * _create_object
1204
-     * Attempts to instantiate the requested class via any of the
1205
-     * commonly used instantiation methods employed throughout EE.
1206
-     * The priority for instantiation is as follows:
1207
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1208
-     *        - model objects via their 'new_instance_from_db' method
1209
-     *        - model objects via their 'new_instance' method
1210
-     *        - "singleton" classes" via their 'instance' method
1211
-     *    - standard instantiable classes via their __constructor
1212
-     * Prior to instantiation, if the classname exists in the dependency_map,
1213
-     * then the constructor for the requested class will be examined to determine
1214
-     * if any dependencies exist, and if they can be injected.
1215
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1216
-     *
1217
-     * @param string $class_name
1218
-     * @param array  $arguments
1219
-     * @param string $type
1220
-     * @param bool   $from_db
1221
-     * @return null|object|bool
1222
-     * @throws InvalidArgumentException
1223
-     * @throws InvalidInterfaceException
1224
-     * @throws EE_Error
1225
-     * @throws ReflectionException
1226
-     * @throws InvalidDataTypeException
1227
-     */
1228
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1229
-    {
1230
-        // create reflection
1231
-        $reflector = $this->mirror->getReflectionClass($class_name);
1232
-        // make sure arguments are an array
1233
-        $arguments = is_array($arguments)
1234
-            ? $arguments
1235
-            : array($arguments);
1236
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1237
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1238
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1239
-            ? $arguments
1240
-            : array($arguments);
1241
-        // attempt to inject dependencies ?
1242
-        if ($this->_dependency_map->has($class_name)) {
1243
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1244
-        }
1245
-        // instantiate the class if possible
1246
-        if ($reflector->isAbstract()) {
1247
-            // nothing to instantiate, loading file was enough
1248
-            // does not throw an exception so $instantiation_mode is unused
1249
-            // $instantiation_mode = "1) no constructor abstract class";
1250
-            return true;
1251
-        }
1252
-        if (
1253
-            empty($arguments)
1254
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1255
-            && $reflector->isInstantiable()
1256
-        ) {
1257
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1258
-            // $instantiation_mode = "2) no constructor but instantiable";
1259
-            return $reflector->newInstance();
1260
-        }
1261
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1262
-            // $instantiation_mode = "3) new_instance_from_db()";
1263
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1264
-        }
1265
-        if (method_exists($class_name, 'new_instance')) {
1266
-            // $instantiation_mode = "4) new_instance()";
1267
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1268
-        }
1269
-        if (method_exists($class_name, 'instance')) {
1270
-            // $instantiation_mode = "5) instance()";
1271
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1272
-        }
1273
-        if ($reflector->isInstantiable()) {
1274
-            // $instantiation_mode = "6) constructor";
1275
-            return $reflector->newInstanceArgs($arguments);
1276
-        }
1277
-        // heh ? something's not right !
1278
-        throw new EE_Error(
1279
-            sprintf(
1280
-                esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1281
-                $type,
1282
-                $class_name
1283
-            )
1284
-        );
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1290
-     * @param array $array
1291
-     * @return bool
1292
-     */
1293
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1294
-    {
1295
-        return ! empty($array)
1296
-            ? array_keys($array) === range(0, count($array) - 1)
1297
-            : true;
1298
-    }
1299
-
1300
-
1301
-    /**
1302
-     * _resolve_dependencies
1303
-     * examines the constructor for the requested class to determine
1304
-     * if any dependencies exist, and if they can be injected.
1305
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1306
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1307
-     * For example:
1308
-     *        if attempting to load a class "Foo" with the following constructor:
1309
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1310
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1311
-     *        but only IF they are NOT already present in the incoming arguments array,
1312
-     *        and the correct classes can be loaded
1313
-     *
1314
-     * @param ReflectionClass $reflector
1315
-     * @param string          $class_name
1316
-     * @param array           $arguments
1317
-     * @return array
1318
-     * @throws InvalidArgumentException
1319
-     * @throws InvalidDataTypeException
1320
-     * @throws InvalidInterfaceException
1321
-     * @throws ReflectionException
1322
-     */
1323
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1324
-    {
1325
-        // let's examine the constructor
1326
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1327
-        // whu? huh? nothing?
1328
-        if (! $constructor) {
1329
-            return $arguments;
1330
-        }
1331
-        // get constructor parameters
1332
-        $params = $this->mirror->getParametersFromReflection($reflector);
1333
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1334
-        $argument_keys = array_keys($arguments);
1335
-        // now loop thru all of the constructors expected parameters
1336
-        foreach ($params as $index => $param) {
1337
-            try {
1338
-                // is this a dependency for a specific class ?
1339
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1340
-            } catch (ReflectionException $exception) {
1341
-                // uh-oh... most likely a legacy class that has not been autoloaded
1342
-                // let's try to derive the classname from what we have now
1343
-                // and hope that the property var name is close to the class name
1344
-                $param_class = $param->getName();
1345
-                $param_class = str_replace('_', ' ', $param_class);
1346
-                $param_class = ucwords($param_class);
1347
-                $param_class = str_replace(' ', '_', $param_class);
1348
-            }
1349
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1350
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1351
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1352
-                : $param_class;
1353
-            if (
1354
-                // param is not even a class
1355
-                $param_class === null
1356
-                // and something already exists in the incoming arguments for this param
1357
-                && array_key_exists($index, $argument_keys)
1358
-                && array_key_exists($argument_keys[ $index ], $arguments)
1359
-            ) {
1360
-                // so let's skip this argument and move on to the next
1361
-                continue;
1362
-            }
1363
-            if (
1364
-                // 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 (
1373
-                // parameter is type hinted as a class, and should be injected
1374
-                $param_class !== null
1375
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1376
-            ) {
1377
-                $arguments = $this->_resolve_dependency(
1378
-                    $class_name,
1379
-                    $param_class,
1380
-                    $arguments,
1381
-                    $index
1382
-                );
1383
-            }
1384
-            if (empty($arguments[ $index ])) {
1385
-                $default_value = $this->mirror->getParameterDefaultValue(
1386
-                    $param,
1387
-                    $class_name,
1388
-                    $index
1389
-                );
1390
-                // if there's no default value, and the incoming argument is an array (albeit empty), then use that
1391
-                $arguments[ $index ] = $default_value === null
1392
-                                 && isset($arguments[ $index ])
1393
-                                 && is_array($arguments[ $index ])
1394
-                    ? $arguments[ $index ]
1395
-                    : $default_value;
1396
-            }
1397
-        }
1398
-        return $arguments;
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * @param string $class_name
1404
-     * @param string $param_class
1405
-     * @param array  $arguments
1406
-     * @param mixed  $index
1407
-     * @return array
1408
-     * @throws InvalidArgumentException
1409
-     * @throws InvalidInterfaceException
1410
-     * @throws InvalidDataTypeException
1411
-     */
1412
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1413
-    {
1414
-        $dependency = null;
1415
-        // should dependency be loaded from cache ?
1416
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1417
-            $class_name,
1418
-            $param_class
1419
-        );
1420
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1421
-        // we might have a dependency...
1422
-        // let's MAYBE try and find it in our cache if that's what's been requested
1423
-        $cached_class = $cache_on
1424
-            ? $this->_get_cached_class($param_class)
1425
-            : null;
1426
-        // and grab it if it exists
1427
-        if ($cached_class instanceof $param_class) {
1428
-            $dependency = $cached_class;
1429
-        } elseif ($param_class !== $class_name) {
1430
-            // obtain the loader method from the dependency map
1431
-            $loader = $this->_dependency_map->class_loader($param_class);
1432
-            // is loader a custom closure ?
1433
-            if ($loader instanceof Closure) {
1434
-                $dependency = $loader($arguments);
1435
-            } else {
1436
-                // set the cache on property for the recursive loading call
1437
-                $this->_cache_on = $cache_on;
1438
-                // if not, then let's try and load it via the registry
1439
-                if ($loader && method_exists($this, $loader)) {
1440
-                    $dependency = $this->{$loader}($param_class);
1441
-                } else {
1442
-                    $dependency = LoaderFactory::getLoader()->load(
1443
-                        $param_class,
1444
-                        array(),
1445
-                        $cache_on
1446
-                    );
1447
-                }
1448
-            }
1449
-        }
1450
-        // did we successfully find the correct dependency ?
1451
-        if ($dependency instanceof $param_class) {
1452
-            // then let's inject it into the incoming array of arguments at the correct location
1453
-            $arguments[ $index ] = $dependency;
1454
-        }
1455
-        return $arguments;
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1461
-     *
1462
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1463
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1464
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1465
-     * @param array  $arguments
1466
-     * @return object
1467
-     */
1468
-    public static function factory($classname, $arguments = array())
1469
-    {
1470
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1471
-        if ($loader instanceof Closure) {
1472
-            return $loader($arguments);
1473
-        }
1474
-        if (method_exists(self::instance(), $loader)) {
1475
-            return self::instance()->{$loader}($classname, $arguments);
1476
-        }
1477
-        return null;
1478
-    }
1479
-
1480
-
1481
-    /**
1482
-     * Gets the addon by its class name
1483
-     *
1484
-     * @param string $class_name
1485
-     * @return EE_Addon
1486
-     */
1487
-    public function getAddon($class_name)
1488
-    {
1489
-        $class_name = str_replace('\\', '_', $class_name);
1490
-        if (isset($this->addons->{$class_name})) {
1491
-            return $this->addons->{$class_name};
1492
-        } else {
1493
-            return null;
1494
-        }
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * removes the addon from the internal cache
1500
-     *
1501
-     * @param string $class_name
1502
-     * @return void
1503
-     */
1504
-    public function removeAddon($class_name)
1505
-    {
1506
-        $class_name = str_replace('\\', '_', $class_name);
1507
-        $this->addons->remove($class_name);
1508
-    }
1509
-
1510
-
1511
-    /**
1512
-     * Gets the addon by its name/slug (not classname. For that, just
1513
-     * use the get_addon() method above
1514
-     *
1515
-     * @param string $name
1516
-     * @return EE_Addon
1517
-     */
1518
-    public function get_addon_by_name($name)
1519
-    {
1520
-        foreach ($this->addons as $addon) {
1521
-            if ($addon->name() === $name) {
1522
-                return $addon;
1523
-            }
1524
-        }
1525
-        return null;
1526
-    }
1527
-
1528
-
1529
-    /**
1530
-     * Gets an array of all the registered addons, where the keys are their names.
1531
-     * (ie, what each returns for their name() function)
1532
-     * They're already available on EE_Registry::instance()->addons as properties,
1533
-     * where each property's name is the addon's classname,
1534
-     * So if you just want to get the addon by classname,
1535
-     * OR use the get_addon() method above.
1536
-     * PLEASE  NOTE:
1537
-     * addons with Fully Qualified Class Names
1538
-     * have had the namespace separators converted to underscores,
1539
-     * so a classname like Fully\Qualified\ClassName
1540
-     * would have been converted to Fully_Qualified_ClassName
1541
-     *
1542
-     * @return EE_Addon[] where the KEYS are the addon's name()
1543
-     */
1544
-    public function get_addons_by_name()
1545
-    {
1546
-        $addons = array();
1547
-        foreach ($this->addons as $addon) {
1548
-            $addons[ $addon->name() ] = $addon;
1549
-        }
1550
-        return $addons;
1551
-    }
1552
-
1553
-
1554
-    /**
1555
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1556
-     * a stale copy of it around
1557
-     *
1558
-     * @param string $model_name
1559
-     * @return \EEM_Base
1560
-     * @throws \EE_Error
1561
-     */
1562
-    public function reset_model($model_name)
1563
-    {
1564
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1565
-            ? "EEM_{$model_name}"
1566
-            : $model_name;
1567
-        if (! $this->LIB->has($model_class_name)) {
1568
-            return null;
1569
-        }
1570
-        $model = $this->LIB->get($model_class_name);
1571
-        if (! $model instanceof EEM_Base) {
1572
-            return null;
1573
-        }
1574
-        // get that model reset it and make sure we nuke the old reference to it
1575
-        if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1576
-            $this->LIB->remove($model_class_name);
1577
-            $this->LIB->add($model_class_name, $model->reset());
1578
-        } else {
1579
-            throw new EE_Error(
1580
-                sprintf(
1581
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1582
-                    $model_name
1583
-                )
1584
-            );
1585
-        }
1586
-        return $model;
1587
-    }
1588
-
1589
-
1590
-    /**
1591
-     * Resets the registry.
1592
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1593
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1594
-     * - $_dependency_map
1595
-     * - $_class_abbreviations
1596
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1597
-     * - $REQ:  Still on the same request so no need to change.
1598
-     * - $CAP: There is no site specific state in the EE_Capability class.
1599
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1600
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1601
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1602
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1603
-     *             switch or on the restore.
1604
-     * - $modules
1605
-     * - $shortcodes
1606
-     * - $widgets
1607
-     *
1608
-     * @param boolean $hard             [deprecated]
1609
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1610
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1611
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1612
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1613
-     *                                  client
1614
-     *                                  code instead can just change the model context to a different blog id if
1615
-     *                                  necessary
1616
-     * @return EE_Registry
1617
-     * @throws InvalidInterfaceException
1618
-     * @throws InvalidDataTypeException
1619
-     * @throws EE_Error
1620
-     * @throws ReflectionException
1621
-     * @throws InvalidArgumentException
1622
-     */
1623
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1624
-    {
1625
-        $instance = self::instance();
1626
-        $instance->_cache_on = true;
1627
-        // reset some "special" classes
1628
-        EEH_Activation::reset();
1629
-        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1630
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1631
-        $instance->CART = null;
1632
-        $instance->MRM = null;
1633
-        $instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1634
-            'EventEspresso\core\services\assets\Registry'
1635
-        );
1636
-        // messages reset
1637
-        EED_Messages::reset();
1638
-        // handle of objects cached on LIB
1639
-        foreach (array('LIB', 'modules') as $cache) {
1640
-            foreach ($instance->{$cache} as $class_name => $class) {
1641
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1642
-                    unset($instance->{$cache}->{$class_name});
1643
-                }
1644
-            }
1645
-        }
1646
-        return $instance;
1647
-    }
1648
-
1649
-
1650
-    /**
1651
-     * if passed object implements ResettableInterface, then call it's reset() method
1652
-     * if passed object implements InterminableInterface, then return false,
1653
-     * to indicate that it should NOT be cleared from the Registry cache
1654
-     *
1655
-     * @param      $object
1656
-     * @param bool $reset_models
1657
-     * @return bool returns true if cached object should be unset
1658
-     */
1659
-    private static function _reset_and_unset_object($object, $reset_models)
1660
-    {
1661
-        if (! is_object($object)) {
1662
-            // don't unset anything that's not an object
1663
-            return false;
1664
-        }
1665
-        if ($object instanceof EED_Module) {
1666
-            $object::reset();
1667
-            // don't unset modules
1668
-            return false;
1669
-        }
1670
-        if ($object instanceof ResettableInterface) {
1671
-            if ($object instanceof EEM_Base) {
1672
-                if ($reset_models) {
1673
-                    $object->reset();
1674
-                    return true;
1675
-                }
1676
-                return false;
1677
-            }
1678
-            $object->reset();
1679
-            return true;
1680
-        }
1681
-        if (! $object instanceof InterminableInterface) {
1682
-            return true;
1683
-        }
1684
-        return false;
1685
-    }
1686
-
1687
-
1688
-    /**
1689
-     * Gets all the custom post type models defined
1690
-     *
1691
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1692
-     */
1693
-    public function cpt_models()
1694
-    {
1695
-        $cpt_models = array();
1696
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1697
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1698
-                $cpt_models[ $short_name ] = $classname;
1699
-            }
1700
-        }
1701
-        return $cpt_models;
1702
-    }
1703
-
1704
-
1705
-    /**
1706
-     * @return \EE_Config
1707
-     */
1708
-    public static function CFG()
1709
-    {
1710
-        return self::instance()->CFG;
1711
-    }
1712
-
1713
-
1714
-    /**
1715
-     * @deprecated 4.9.62.p
1716
-     * @param string $class_name
1717
-     * @return ReflectionClass
1718
-     * @throws ReflectionException
1719
-     * @throws InvalidDataTypeException
1720
-     */
1721
-    public function get_ReflectionClass($class_name)
1722
-    {
1723
-        return $this->mirror->getReflectionClass($class_name);
1724
-    }
982
+				! $this->object_identifier->hasArguments($object_identifier)
983
+				// but previously cached class with args was found
984
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
985
+			) {
986
+				return $object;
987
+			}
988
+		}
989
+		return null;
990
+	}
991
+
992
+
993
+	/**
994
+	 * removes a cached version of the requested class
995
+	 *
996
+	 * @param string  $class_name
997
+	 * @param boolean $addon
998
+	 * @param array   $arguments
999
+	 * @return boolean
1000
+	 */
1001
+	public function clear_cached_class(
1002
+		$class_name,
1003
+		$addon = false,
1004
+		$arguments = array()
1005
+	) {
1006
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
1007
+		// check if class has already been loaded, and return it if it has been
1008
+		if (isset($this->{$class_abbreviation})) {
1009
+			$this->{$class_abbreviation} = null;
1010
+			return true;
1011
+		}
1012
+		$class_name = str_replace('\\', '_', $class_name);
1013
+		if (isset($this->{$class_name})) {
1014
+			$this->{$class_name} = null;
1015
+			return true;
1016
+		}
1017
+		if ($addon && $this->addons->has($class_name)) {
1018
+			$this->addons->remove($class_name);
1019
+			return true;
1020
+		}
1021
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1022
+		if ($this->LIB->has($class_name)) {
1023
+			$this->LIB->remove($class_name);
1024
+			return true;
1025
+		}
1026
+		return false;
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * _set_cached_class
1032
+	 * attempts to cache the instantiated class locally
1033
+	 * in one of the following places, in the following order:
1034
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1035
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1036
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1037
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1038
+	 *
1039
+	 * @param object $class_obj
1040
+	 * @param string $class_name
1041
+	 * @param string $class_prefix
1042
+	 * @param bool   $from_db
1043
+	 * @param array  $arguments
1044
+	 * @return void
1045
+	 */
1046
+	protected function _set_cached_class(
1047
+		$class_obj,
1048
+		$class_name,
1049
+		$class_prefix = '',
1050
+		$from_db = false,
1051
+		$arguments = array()
1052
+	) {
1053
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1054
+			return;
1055
+		}
1056
+		// return newly instantiated class
1057
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1058
+		if ($class_abbreviation) {
1059
+			$this->{$class_abbreviation} = $class_obj;
1060
+			return;
1061
+		}
1062
+		$class_name = str_replace('\\', '_', $class_name);
1063
+		if (property_exists($this, $class_name)) {
1064
+			$this->{$class_name} = $class_obj;
1065
+			return;
1066
+		}
1067
+		if ($class_prefix === 'addon') {
1068
+			$this->addons->add($class_name, $class_obj);
1069
+			return;
1070
+		}
1071
+		if (! $from_db) {
1072
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1073
+			$this->LIB->add($class_name, $class_obj);
1074
+		}
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * attempts to find a full valid filepath for the requested class.
1080
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1081
+	 * then returns that path if the target file has been found and is readable
1082
+	 *
1083
+	 * @param string $class_name
1084
+	 * @param string $type
1085
+	 * @param array  $file_paths
1086
+	 * @return string | bool
1087
+	 */
1088
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
1089
+	{
1090
+		// make sure $file_paths is an array
1091
+		$file_paths = is_array($file_paths)
1092
+			? $file_paths
1093
+			: array($file_paths);
1094
+		// cycle thru paths
1095
+		foreach ($file_paths as $key => $file_path) {
1096
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1097
+			$file_path = $file_path
1098
+				? str_replace(array('/', '\\'), '/', $file_path)
1099
+				: EE_CLASSES;
1100
+			// prep file type
1101
+			$type = ! empty($type)
1102
+				? trim($type, '.') . '.'
1103
+				: '';
1104
+			// build full file path
1105
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1106
+			// does the file exist and can be read ?
1107
+			if (is_readable($file_paths[ $key ])) {
1108
+				return $file_paths[ $key ];
1109
+			}
1110
+		}
1111
+		return false;
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * basically just performs a require_once()
1117
+	 * but with some error handling
1118
+	 *
1119
+	 * @param  string $path
1120
+	 * @param  string $class_name
1121
+	 * @param  string $type
1122
+	 * @param  array  $file_paths
1123
+	 * @return bool
1124
+	 * @throws EE_Error
1125
+	 * @throws ReflectionException
1126
+	 */
1127
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1128
+	{
1129
+		$this->resolve_legacy_class_parent($class_name);
1130
+		// don't give up! you gotta...
1131
+		try {
1132
+			// does the file exist and can it be read ?
1133
+			if (! $path) {
1134
+				// just in case the file has already been autoloaded,
1135
+				// but discrepancies in the naming schema are preventing it from
1136
+				// being loaded via one of the EE_Registry::load_*() methods,
1137
+				// then let's try one last hail mary before throwing an exception
1138
+				// and call class_exists() again, but with autoloading turned ON
1139
+				if (class_exists($class_name)) {
1140
+					return true;
1141
+				}
1142
+				// so sorry, can't find the file
1143
+				throw new EE_Error(
1144
+					sprintf(
1145
+						esc_html__(
1146
+							'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',
1147
+							'event_espresso'
1148
+						),
1149
+						trim($type, '.'),
1150
+						$class_name,
1151
+						'<br />' . implode(',<br />', $file_paths)
1152
+					)
1153
+				);
1154
+			}
1155
+			// get the file
1156
+			require_once($path);
1157
+			// if the class isn't already declared somewhere
1158
+			if (class_exists($class_name, false) === false) {
1159
+				// so sorry, not a class
1160
+				throw new EE_Error(
1161
+					sprintf(
1162
+						esc_html__(
1163
+							'The %s file %s does not appear to contain the %s Class.',
1164
+							'event_espresso'
1165
+						),
1166
+						$type,
1167
+						$path,
1168
+						$class_name
1169
+					)
1170
+				);
1171
+			}
1172
+		} catch (EE_Error $e) {
1173
+			$e->get_error();
1174
+			return false;
1175
+		}
1176
+		return true;
1177
+	}
1178
+
1179
+
1180
+	/**
1181
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1182
+	 * before their class declaration in order to ensure that the parent class was loaded.
1183
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1184
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1185
+	 *
1186
+	 * @param string $class_name
1187
+	 */
1188
+	protected function resolve_legacy_class_parent($class_name = '')
1189
+	{
1190
+		try {
1191
+			$legacy_parent_class_map = array(
1192
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1193
+			);
1194
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1195
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1196
+			}
1197
+		} catch (Exception $exception) {
1198
+		}
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * _create_object
1204
+	 * Attempts to instantiate the requested class via any of the
1205
+	 * commonly used instantiation methods employed throughout EE.
1206
+	 * The priority for instantiation is as follows:
1207
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1208
+	 *        - model objects via their 'new_instance_from_db' method
1209
+	 *        - model objects via their 'new_instance' method
1210
+	 *        - "singleton" classes" via their 'instance' method
1211
+	 *    - standard instantiable classes via their __constructor
1212
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1213
+	 * then the constructor for the requested class will be examined to determine
1214
+	 * if any dependencies exist, and if they can be injected.
1215
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1216
+	 *
1217
+	 * @param string $class_name
1218
+	 * @param array  $arguments
1219
+	 * @param string $type
1220
+	 * @param bool   $from_db
1221
+	 * @return null|object|bool
1222
+	 * @throws InvalidArgumentException
1223
+	 * @throws InvalidInterfaceException
1224
+	 * @throws EE_Error
1225
+	 * @throws ReflectionException
1226
+	 * @throws InvalidDataTypeException
1227
+	 */
1228
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1229
+	{
1230
+		// create reflection
1231
+		$reflector = $this->mirror->getReflectionClass($class_name);
1232
+		// make sure arguments are an array
1233
+		$arguments = is_array($arguments)
1234
+			? $arguments
1235
+			: array($arguments);
1236
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1237
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1238
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1239
+			? $arguments
1240
+			: array($arguments);
1241
+		// attempt to inject dependencies ?
1242
+		if ($this->_dependency_map->has($class_name)) {
1243
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1244
+		}
1245
+		// instantiate the class if possible
1246
+		if ($reflector->isAbstract()) {
1247
+			// nothing to instantiate, loading file was enough
1248
+			// does not throw an exception so $instantiation_mode is unused
1249
+			// $instantiation_mode = "1) no constructor abstract class";
1250
+			return true;
1251
+		}
1252
+		if (
1253
+			empty($arguments)
1254
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1255
+			&& $reflector->isInstantiable()
1256
+		) {
1257
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1258
+			// $instantiation_mode = "2) no constructor but instantiable";
1259
+			return $reflector->newInstance();
1260
+		}
1261
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1262
+			// $instantiation_mode = "3) new_instance_from_db()";
1263
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1264
+		}
1265
+		if (method_exists($class_name, 'new_instance')) {
1266
+			// $instantiation_mode = "4) new_instance()";
1267
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1268
+		}
1269
+		if (method_exists($class_name, 'instance')) {
1270
+			// $instantiation_mode = "5) instance()";
1271
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1272
+		}
1273
+		if ($reflector->isInstantiable()) {
1274
+			// $instantiation_mode = "6) constructor";
1275
+			return $reflector->newInstanceArgs($arguments);
1276
+		}
1277
+		// heh ? something's not right !
1278
+		throw new EE_Error(
1279
+			sprintf(
1280
+				esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1281
+				$type,
1282
+				$class_name
1283
+			)
1284
+		);
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1290
+	 * @param array $array
1291
+	 * @return bool
1292
+	 */
1293
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1294
+	{
1295
+		return ! empty($array)
1296
+			? array_keys($array) === range(0, count($array) - 1)
1297
+			: true;
1298
+	}
1299
+
1300
+
1301
+	/**
1302
+	 * _resolve_dependencies
1303
+	 * examines the constructor for the requested class to determine
1304
+	 * if any dependencies exist, and if they can be injected.
1305
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1306
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1307
+	 * For example:
1308
+	 *        if attempting to load a class "Foo" with the following constructor:
1309
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1310
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1311
+	 *        but only IF they are NOT already present in the incoming arguments array,
1312
+	 *        and the correct classes can be loaded
1313
+	 *
1314
+	 * @param ReflectionClass $reflector
1315
+	 * @param string          $class_name
1316
+	 * @param array           $arguments
1317
+	 * @return array
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws InvalidDataTypeException
1320
+	 * @throws InvalidInterfaceException
1321
+	 * @throws ReflectionException
1322
+	 */
1323
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1324
+	{
1325
+		// let's examine the constructor
1326
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1327
+		// whu? huh? nothing?
1328
+		if (! $constructor) {
1329
+			return $arguments;
1330
+		}
1331
+		// get constructor parameters
1332
+		$params = $this->mirror->getParametersFromReflection($reflector);
1333
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1334
+		$argument_keys = array_keys($arguments);
1335
+		// now loop thru all of the constructors expected parameters
1336
+		foreach ($params as $index => $param) {
1337
+			try {
1338
+				// is this a dependency for a specific class ?
1339
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1340
+			} catch (ReflectionException $exception) {
1341
+				// uh-oh... most likely a legacy class that has not been autoloaded
1342
+				// let's try to derive the classname from what we have now
1343
+				// and hope that the property var name is close to the class name
1344
+				$param_class = $param->getName();
1345
+				$param_class = str_replace('_', ' ', $param_class);
1346
+				$param_class = ucwords($param_class);
1347
+				$param_class = str_replace(' ', '_', $param_class);
1348
+			}
1349
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1350
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1351
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1352
+				: $param_class;
1353
+			if (
1354
+				// param is not even a class
1355
+				$param_class === null
1356
+				// and something already exists in the incoming arguments for this param
1357
+				&& array_key_exists($index, $argument_keys)
1358
+				&& array_key_exists($argument_keys[ $index ], $arguments)
1359
+			) {
1360
+				// so let's skip this argument and move on to the next
1361
+				continue;
1362
+			}
1363
+			if (
1364
+				// 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 (
1373
+				// parameter is type hinted as a class, and should be injected
1374
+				$param_class !== null
1375
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1376
+			) {
1377
+				$arguments = $this->_resolve_dependency(
1378
+					$class_name,
1379
+					$param_class,
1380
+					$arguments,
1381
+					$index
1382
+				);
1383
+			}
1384
+			if (empty($arguments[ $index ])) {
1385
+				$default_value = $this->mirror->getParameterDefaultValue(
1386
+					$param,
1387
+					$class_name,
1388
+					$index
1389
+				);
1390
+				// if there's no default value, and the incoming argument is an array (albeit empty), then use that
1391
+				$arguments[ $index ] = $default_value === null
1392
+								 && isset($arguments[ $index ])
1393
+								 && is_array($arguments[ $index ])
1394
+					? $arguments[ $index ]
1395
+					: $default_value;
1396
+			}
1397
+		}
1398
+		return $arguments;
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * @param string $class_name
1404
+	 * @param string $param_class
1405
+	 * @param array  $arguments
1406
+	 * @param mixed  $index
1407
+	 * @return array
1408
+	 * @throws InvalidArgumentException
1409
+	 * @throws InvalidInterfaceException
1410
+	 * @throws InvalidDataTypeException
1411
+	 */
1412
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1413
+	{
1414
+		$dependency = null;
1415
+		// should dependency be loaded from cache ?
1416
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1417
+			$class_name,
1418
+			$param_class
1419
+		);
1420
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1421
+		// we might have a dependency...
1422
+		// let's MAYBE try and find it in our cache if that's what's been requested
1423
+		$cached_class = $cache_on
1424
+			? $this->_get_cached_class($param_class)
1425
+			: null;
1426
+		// and grab it if it exists
1427
+		if ($cached_class instanceof $param_class) {
1428
+			$dependency = $cached_class;
1429
+		} elseif ($param_class !== $class_name) {
1430
+			// obtain the loader method from the dependency map
1431
+			$loader = $this->_dependency_map->class_loader($param_class);
1432
+			// is loader a custom closure ?
1433
+			if ($loader instanceof Closure) {
1434
+				$dependency = $loader($arguments);
1435
+			} else {
1436
+				// set the cache on property for the recursive loading call
1437
+				$this->_cache_on = $cache_on;
1438
+				// if not, then let's try and load it via the registry
1439
+				if ($loader && method_exists($this, $loader)) {
1440
+					$dependency = $this->{$loader}($param_class);
1441
+				} else {
1442
+					$dependency = LoaderFactory::getLoader()->load(
1443
+						$param_class,
1444
+						array(),
1445
+						$cache_on
1446
+					);
1447
+				}
1448
+			}
1449
+		}
1450
+		// did we successfully find the correct dependency ?
1451
+		if ($dependency instanceof $param_class) {
1452
+			// then let's inject it into the incoming array of arguments at the correct location
1453
+			$arguments[ $index ] = $dependency;
1454
+		}
1455
+		return $arguments;
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1461
+	 *
1462
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1463
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1464
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1465
+	 * @param array  $arguments
1466
+	 * @return object
1467
+	 */
1468
+	public static function factory($classname, $arguments = array())
1469
+	{
1470
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1471
+		if ($loader instanceof Closure) {
1472
+			return $loader($arguments);
1473
+		}
1474
+		if (method_exists(self::instance(), $loader)) {
1475
+			return self::instance()->{$loader}($classname, $arguments);
1476
+		}
1477
+		return null;
1478
+	}
1479
+
1480
+
1481
+	/**
1482
+	 * Gets the addon by its class name
1483
+	 *
1484
+	 * @param string $class_name
1485
+	 * @return EE_Addon
1486
+	 */
1487
+	public function getAddon($class_name)
1488
+	{
1489
+		$class_name = str_replace('\\', '_', $class_name);
1490
+		if (isset($this->addons->{$class_name})) {
1491
+			return $this->addons->{$class_name};
1492
+		} else {
1493
+			return null;
1494
+		}
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * removes the addon from the internal cache
1500
+	 *
1501
+	 * @param string $class_name
1502
+	 * @return void
1503
+	 */
1504
+	public function removeAddon($class_name)
1505
+	{
1506
+		$class_name = str_replace('\\', '_', $class_name);
1507
+		$this->addons->remove($class_name);
1508
+	}
1509
+
1510
+
1511
+	/**
1512
+	 * Gets the addon by its name/slug (not classname. For that, just
1513
+	 * use the get_addon() method above
1514
+	 *
1515
+	 * @param string $name
1516
+	 * @return EE_Addon
1517
+	 */
1518
+	public function get_addon_by_name($name)
1519
+	{
1520
+		foreach ($this->addons as $addon) {
1521
+			if ($addon->name() === $name) {
1522
+				return $addon;
1523
+			}
1524
+		}
1525
+		return null;
1526
+	}
1527
+
1528
+
1529
+	/**
1530
+	 * Gets an array of all the registered addons, where the keys are their names.
1531
+	 * (ie, what each returns for their name() function)
1532
+	 * They're already available on EE_Registry::instance()->addons as properties,
1533
+	 * where each property's name is the addon's classname,
1534
+	 * So if you just want to get the addon by classname,
1535
+	 * OR use the get_addon() method above.
1536
+	 * PLEASE  NOTE:
1537
+	 * addons with Fully Qualified Class Names
1538
+	 * have had the namespace separators converted to underscores,
1539
+	 * so a classname like Fully\Qualified\ClassName
1540
+	 * would have been converted to Fully_Qualified_ClassName
1541
+	 *
1542
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1543
+	 */
1544
+	public function get_addons_by_name()
1545
+	{
1546
+		$addons = array();
1547
+		foreach ($this->addons as $addon) {
1548
+			$addons[ $addon->name() ] = $addon;
1549
+		}
1550
+		return $addons;
1551
+	}
1552
+
1553
+
1554
+	/**
1555
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1556
+	 * a stale copy of it around
1557
+	 *
1558
+	 * @param string $model_name
1559
+	 * @return \EEM_Base
1560
+	 * @throws \EE_Error
1561
+	 */
1562
+	public function reset_model($model_name)
1563
+	{
1564
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1565
+			? "EEM_{$model_name}"
1566
+			: $model_name;
1567
+		if (! $this->LIB->has($model_class_name)) {
1568
+			return null;
1569
+		}
1570
+		$model = $this->LIB->get($model_class_name);
1571
+		if (! $model instanceof EEM_Base) {
1572
+			return null;
1573
+		}
1574
+		// get that model reset it and make sure we nuke the old reference to it
1575
+		if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1576
+			$this->LIB->remove($model_class_name);
1577
+			$this->LIB->add($model_class_name, $model->reset());
1578
+		} else {
1579
+			throw new EE_Error(
1580
+				sprintf(
1581
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1582
+					$model_name
1583
+				)
1584
+			);
1585
+		}
1586
+		return $model;
1587
+	}
1588
+
1589
+
1590
+	/**
1591
+	 * Resets the registry.
1592
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1593
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1594
+	 * - $_dependency_map
1595
+	 * - $_class_abbreviations
1596
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1597
+	 * - $REQ:  Still on the same request so no need to change.
1598
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1599
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1600
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1601
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1602
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1603
+	 *             switch or on the restore.
1604
+	 * - $modules
1605
+	 * - $shortcodes
1606
+	 * - $widgets
1607
+	 *
1608
+	 * @param boolean $hard             [deprecated]
1609
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1610
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1611
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1612
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1613
+	 *                                  client
1614
+	 *                                  code instead can just change the model context to a different blog id if
1615
+	 *                                  necessary
1616
+	 * @return EE_Registry
1617
+	 * @throws InvalidInterfaceException
1618
+	 * @throws InvalidDataTypeException
1619
+	 * @throws EE_Error
1620
+	 * @throws ReflectionException
1621
+	 * @throws InvalidArgumentException
1622
+	 */
1623
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1624
+	{
1625
+		$instance = self::instance();
1626
+		$instance->_cache_on = true;
1627
+		// reset some "special" classes
1628
+		EEH_Activation::reset();
1629
+		$hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1630
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1631
+		$instance->CART = null;
1632
+		$instance->MRM = null;
1633
+		$instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1634
+			'EventEspresso\core\services\assets\Registry'
1635
+		);
1636
+		// messages reset
1637
+		EED_Messages::reset();
1638
+		// handle of objects cached on LIB
1639
+		foreach (array('LIB', 'modules') as $cache) {
1640
+			foreach ($instance->{$cache} as $class_name => $class) {
1641
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1642
+					unset($instance->{$cache}->{$class_name});
1643
+				}
1644
+			}
1645
+		}
1646
+		return $instance;
1647
+	}
1648
+
1649
+
1650
+	/**
1651
+	 * if passed object implements ResettableInterface, then call it's reset() method
1652
+	 * if passed object implements InterminableInterface, then return false,
1653
+	 * to indicate that it should NOT be cleared from the Registry cache
1654
+	 *
1655
+	 * @param      $object
1656
+	 * @param bool $reset_models
1657
+	 * @return bool returns true if cached object should be unset
1658
+	 */
1659
+	private static function _reset_and_unset_object($object, $reset_models)
1660
+	{
1661
+		if (! is_object($object)) {
1662
+			// don't unset anything that's not an object
1663
+			return false;
1664
+		}
1665
+		if ($object instanceof EED_Module) {
1666
+			$object::reset();
1667
+			// don't unset modules
1668
+			return false;
1669
+		}
1670
+		if ($object instanceof ResettableInterface) {
1671
+			if ($object instanceof EEM_Base) {
1672
+				if ($reset_models) {
1673
+					$object->reset();
1674
+					return true;
1675
+				}
1676
+				return false;
1677
+			}
1678
+			$object->reset();
1679
+			return true;
1680
+		}
1681
+		if (! $object instanceof InterminableInterface) {
1682
+			return true;
1683
+		}
1684
+		return false;
1685
+	}
1686
+
1687
+
1688
+	/**
1689
+	 * Gets all the custom post type models defined
1690
+	 *
1691
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1692
+	 */
1693
+	public function cpt_models()
1694
+	{
1695
+		$cpt_models = array();
1696
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1697
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1698
+				$cpt_models[ $short_name ] = $classname;
1699
+			}
1700
+		}
1701
+		return $cpt_models;
1702
+	}
1703
+
1704
+
1705
+	/**
1706
+	 * @return \EE_Config
1707
+	 */
1708
+	public static function CFG()
1709
+	{
1710
+		return self::instance()->CFG;
1711
+	}
1712
+
1713
+
1714
+	/**
1715
+	 * @deprecated 4.9.62.p
1716
+	 * @param string $class_name
1717
+	 * @return ReflectionClass
1718
+	 * @throws ReflectionException
1719
+	 * @throws InvalidDataTypeException
1720
+	 */
1721
+	public function get_ReflectionClass($class_name)
1722
+	{
1723
+		return $this->mirror->getReflectionClass($class_name);
1724
+	}
1725 1725
 }
Please login to merge, or discard this patch.