Completed
Branch FET-9795-new-interfaces (f37aef)
by
unknown
92:51 queued 80:52
created

EE_Registry   D

Complexity

Total Complexity 161

Size/Duplication

Total Lines 1413
Duplicated Lines 3.18 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
dl 45
loc 1413
rs 4.4102
c 0
b 0
f 0
wmc 161
lcom 1
cbo 10

50 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 8 2
A __construct() 0 5 1
A localize_i18n_js_strings() 0 10 3
A add_module() 0 12 3
A get_module() 0 4 2
A load_core() 0 16 1
A load_service() 0 11 1
A load_dms() 0 5 1
A load_class() 0 10 1
A load_helper() 0 7 1
A load_lib() 0 12 1
A load_model() 0 9 1
A load_model_class() 0 11 1
A is_model_name() 0 4 2
A load_file() 0 5 1
A load_addon() 0 5 1
C create() 7 42 12
C _load() 7 57 15
C _get_cached_class() 0 23 9
B _resolve_path() 0 19 6
B _require_file() 22 36 4
D _create_object() 0 67 15
A _array_is_numerically_and_sequentially_indexed() 0 4 2
A get_ReflectionClass() 9 10 3
C _resolve_dependencies() 0 54 12
D _resolve_dependency() 0 42 9
B _set_cached_class() 0 17 7
A factory() 0 10 3
A get_addon_by_name() 0 9 3
A get_addons_by_name() 0 8 2
B reset_model() 0 14 6
B initialize() 0 36 1
A init() 0 8 3
B reset() 0 23 4
B _reset_and_unset_object() 0 20 5
A __destruct() 0 3 1
A __call() 0 3 1
A __get() 0 3 1
A __set() 0 3 1
A __isset() 0 3 1
A __unset() 0 3 1
A __sleep() 0 4 1
A __wakeup() 0 3 1
A __toString() 0 4 1
A __invoke() 0 3 1
A __set_state() 0 4 1
A __clone() 0 3 1
A __callStatic() 0 3 1
A cpt_models() 0 10 3
A CFG() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

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

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

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

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

1
<?php
2
3
use EventEspresso\core\interfaces\InterminableInterface;
4
use EventEspresso\core\interfaces\ResettableInterface;
5
use EventEspresso\core\services\assets\Registry;
6
7
defined('EVENT_ESPRESSO_VERSION') || exit;
8
9
10
11
/**
12
 * EE_Registry Class
13
 * Centralized Application Data Storage and Management
14
 *
15
 * @package                   Event Espresso
16
 * @subpackage                core
17
 * @author                    Brent Christensen
18
 */
19
class EE_Registry implements ResettableInterface
20
{
21
22
    /**
23
     *    EE_Registry Object
24
     *
25
     * @var EE_Registry $_instance
26
     * @access    private
27
     */
28
    private static $_instance = null;
29
30
    /**
31
     * @var EE_Dependency_Map $_dependency_map
32
     * @access    protected
33
     */
34
    protected $_dependency_map = null;
35
36
    /**
37
     * @var array $_class_abbreviations
38
     * @access    protected
39
     */
40
    protected $_class_abbreviations = array();
41
42
    /**
43
     * @access public
44
     * @var \EventEspresso\core\services\commands\CommandBusInterface $BUS
45
     */
46
    public $BUS;
47
48
    /**
49
     *    EE_Cart Object
50
     *
51
     * @access    public
52
     * @var    EE_Cart $CART
53
     */
54
    public $CART = null;
55
56
    /**
57
     *    EE_Config Object
58
     *
59
     * @access    public
60
     * @var    EE_Config $CFG
61
     */
62
    public $CFG = null;
63
64
    /**
65
     * EE_Network_Config Object
66
     *
67
     * @access public
68
     * @var EE_Network_Config $NET_CFG
69
     */
70
    public $NET_CFG = null;
71
72
    /**
73
     *    StdClass object for storing library classes in
74
     *
75
     * @public LIB
76
     * @var StdClass $LIB
77
     */
78
    public $LIB = null;
79
80
    /**
81
     *    EE_Request_Handler Object
82
     *
83
     * @access    public
84
     * @var    EE_Request_Handler $REQ
85
     */
86
    public $REQ = null;
87
88
    /**
89
     *    EE_Session Object
90
     *
91
     * @access    public
92
     * @var    EE_Session $SSN
93
     */
94
    public $SSN = null;
95
96
    /**
97
     * holds the ee capabilities object.
98
     *
99
     * @since 4.5.0
100
     * @var EE_Capabilities
101
     */
102
    public $CAP = null;
103
104
    /**
105
     * holds the EE_Message_Resource_Manager object.
106
     *
107
     * @since 4.9.0
108
     * @var EE_Message_Resource_Manager
109
     */
110
    public $MRM = null;
111
112
113
    /**
114
     * Holds the Assets Registry instance
115
     * @var Registry
116
     */
117
    public $AssetsRegistry = null;
118
119
    /**
120
     *    $addons - StdClass object for holding addons which have registered themselves to work with EE core
121
     *
122
     * @access    public
123
     * @var    EE_Addon[]
124
     */
125
    public $addons = null;
126
127
    /**
128
     *    $models
129
     * @access    public
130
     * @var    EEM_Base[] $models keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
131
     */
132
    public $models = array();
133
134
    /**
135
     *    $modules
136
     * @access    public
137
     * @var    EED_Module[] $modules
138
     */
139
    public $modules = null;
140
141
    /**
142
     *    $shortcodes
143
     * @access    public
144
     * @var    EES_Shortcode[] $shortcodes
145
     */
146
    public $shortcodes = null;
147
148
    /**
149
     *    $widgets
150
     * @access    public
151
     * @var    WP_Widget[] $widgets
152
     */
153
    public $widgets = null;
154
155
    /**
156
     * $non_abstract_db_models
157
     * @access public
158
     * @var array this is an array of all implemented model names (i.e. not the parent abstract models, or models
159
     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
160
     * Keys are model "short names" (eg "Event") as used in model relations, and values are
161
     * classnames (eg "EEM_Event")
162
     */
163
    public $non_abstract_db_models = array();
164
165
166
    /**
167
     *    $i18n_js_strings - internationalization for JS strings
168
     *    usage:   EE_Registry::i18n_js_strings['string_key'] = __( 'string to translate.', 'event_espresso' );
169
     *    in js file:  var translatedString = eei18n.string_key;
170
     *
171
     * @access    public
172
     * @var    array
173
     */
174
    public static $i18n_js_strings = array();
175
176
177
    /**
178
     *    $main_file - path to espresso.php
179
     *
180
     * @access    public
181
     * @var    array
182
     */
183
    public $main_file;
184
185
    /**
186
     * array of ReflectionClass objects where the key is the class name
187
     *
188
     * @access    public
189
     * @var ReflectionClass[]
190
     */
191
    public $_reflectors;
192
193
    /**
194
     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
195
     *
196
     * @access    protected
197
     * @var boolean $_cache_on
198
     */
199
    protected $_cache_on = true;
200
201
202
203
    /**
204
     * @singleton method used to instantiate class object
205
     * @access    public
206
     * @param  \EE_Dependency_Map $dependency_map
207
     * @return \EE_Registry instance
208
     */
209
    public static function instance(\EE_Dependency_Map $dependency_map = null)
210
    {
211
        // check if class object is instantiated
212
        if ( ! self::$_instance instanceof EE_Registry) {
213
            self::$_instance = new EE_Registry($dependency_map);
0 ignored issues
show
Bug introduced by
It seems like $dependency_map defined by parameter $dependency_map on line 209 can be null; however, EE_Registry::__construct() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
214
        }
215
        return self::$_instance;
216
    }
217
218
219
220
    /**
221
     *protected constructor to prevent direct creation
222
     *
223
     * @Constructor
224
     * @access protected
225
     * @param  \EE_Dependency_Map $dependency_map
226
     * @return \EE_Registry
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
227
     */
228
    protected function __construct(\EE_Dependency_Map $dependency_map)
229
    {
230
        $this->_dependency_map = $dependency_map;
231
        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
232
    }
233
234
235
236
    /**
237
     * initialize
238
     */
239
    public function initialize()
240
    {
241
        $this->_class_abbreviations = apply_filters(
242
            'FHEE__EE_Registry____construct___class_abbreviations',
243
            array(
244
                'EE_Config'                                       => 'CFG',
245
                'EE_Session'                                      => 'SSN',
246
                'EE_Capabilities'                                 => 'CAP',
247
                'EE_Cart'                                         => 'CART',
248
                'EE_Network_Config'                               => 'NET_CFG',
249
                'EE_Request_Handler'                              => 'REQ',
250
                'EE_Message_Resource_Manager'                     => 'MRM',
251
                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
252
                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
253
            )
254
        );
255
        // class library
256
        $this->LIB = new stdClass();
257
        $this->addons = new stdClass();
258
        $this->modules = new stdClass();
259
        $this->shortcodes = new stdClass();
260
        $this->widgets = new stdClass();
261
        $this->load_core('Base', array(), true);
262
        // add our request and response objects to the cache
263
        $request_loader = $this->_dependency_map->class_loader('EE_Request');
264
        $this->_set_cached_class(
265
            $request_loader(),
266
            'EE_Request'
267
        );
268
        $response_loader = $this->_dependency_map->class_loader('EE_Response');
269
        $this->_set_cached_class(
270
            $response_loader(),
271
            'EE_Response'
272
        );
273
        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
274
    }
275
276
277
278
    /**
279
     *    init
280
     *
281
     * @access    public
282
     * @return    void
283
     */
284
    public function init()
285
    {
286
        // Get current page protocol
287
        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
288
        // Output admin-ajax.php URL with same protocol as current page
289
        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
290
        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
291
    }
292
293
294
295
    /**
296
     * localize_i18n_js_strings
297
     *
298
     * @return string
299
     */
300
    public static function localize_i18n_js_strings()
301
    {
302
        $i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
303
        foreach ($i18n_js_strings as $key => $value) {
304
            if (is_scalar($value)) {
305
                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
306
            }
307
        }
308
        return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
309
    }
310
311
312
313
    /**
314
     * @param mixed string | EED_Module $module
315
     */
316
    public function add_module($module)
317
    {
318
        if ($module instanceof EED_Module) {
319
            $module_class = get_class($module);
320
            $this->modules->{$module_class} = $module;
321
        } else {
322
            if ( ! class_exists('EE_Module_Request_Router')) {
323
                $this->load_core('Module_Request_Router');
324
            }
325
            $this->modules->{$module} = EE_Module_Request_Router::module_factory($module);
326
        }
327
    }
328
329
330
331
    /**
332
     * @param string $module_name
333
     * @return mixed EED_Module | NULL
334
     */
335
    public function get_module($module_name = '')
336
    {
337
        return isset($this->modules->{$module_name}) ? $this->modules->{$module_name} : null;
338
    }
339
340
341
342
    /**
343
     *    loads core classes - must be singletons
344
     *
345
     * @access    public
346
     * @param string $class_name - simple class name ie: session
347
     * @param mixed  $arguments
348
     * @param bool   $load_only
349
     * @return mixed
350
     */
351
    public function load_core($class_name, $arguments = array(), $load_only = false)
352
    {
353
        $core_paths = apply_filters(
354
            'FHEE__EE_Registry__load_core__core_paths',
355
            array(
356
                EE_CORE,
357
                EE_ADMIN,
358
                EE_CPTS,
359
                EE_CORE . 'data_migration_scripts' . DS,
360
                EE_CORE . 'request_stack' . DS,
361
                EE_CORE . 'middleware' . DS,
362
            )
363
        );
364
        // retrieve instantiated class
365
        return $this->_load($core_paths, 'EE_', $class_name, 'core', $arguments, false, true, $load_only);
366
    }
367
368
369
370
    /**
371
     *    loads service classes
372
     *
373
     * @access    public
374
     * @param string $class_name - simple class name ie: session
375
     * @param mixed  $arguments
376
     * @param bool   $load_only
377
     * @return mixed
378
     */
379
    public function load_service($class_name, $arguments = array(), $load_only = false)
380
    {
381
        $service_paths = apply_filters(
382
            'FHEE__EE_Registry__load_service__service_paths',
383
            array(
384
                EE_CORE . 'services' . DS,
385
            )
386
        );
387
        // retrieve instantiated class
388
        return $this->_load($service_paths, 'EE_', $class_name, 'class', $arguments, false, true, $load_only);
389
    }
390
391
392
393
    /**
394
     *    loads data_migration_scripts
395
     *
396
     * @access    public
397
     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
398
     * @param mixed  $arguments
399
     * @return EE_Data_Migration_Script_Base|mixed
400
     */
401
    public function load_dms($class_name, $arguments = array())
402
    {
403
        // retrieve instantiated class
404
        return $this->_load(EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(), 'EE_DMS_', $class_name, 'dms', $arguments, false, false, false);
405
    }
406
407
408
409
    /**
410
     *    loads object creating classes - must be singletons
411
     *
412
     * @param string $class_name - simple class name ie: attendee
413
     * @param mixed  $arguments  - an array of arguments to pass to the class
414
     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to instantiate
415
     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then set this to FALSE (ie. when instantiating model objects from client in a loop)
416
     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate (default)
417
     * @return EE_Base_Class | bool
418
     */
419
    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
420
    {
421
        $paths = apply_filters('FHEE__EE_Registry__load_class__paths', array(
422
            EE_CORE,
423
            EE_CLASSES,
424
            EE_BUSINESS,
425
        ));
426
        // retrieve instantiated class
427
        return $this->_load($paths, 'EE_', $class_name, 'class', $arguments, $from_db, $cache, $load_only);
428
    }
429
430
431
432
    /**
433
     *    loads helper classes - must be singletons
434
     *
435
     * @param string $class_name - simple class name ie: price
436
     * @param mixed  $arguments
437
     * @param bool   $load_only
438
     * @return EEH_Base | bool
439
     */
440
    public function load_helper($class_name, $arguments = array(), $load_only = true)
441
    {
442
        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
443
        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
444
        // retrieve instantiated class
445
        return $this->_load($helper_paths, 'EEH_', $class_name, 'helper', $arguments, false, true, $load_only);
446
    }
447
448
449
450
    /**
451
     *    loads core classes - must be singletons
452
     *
453
     * @access    public
454
     * @param string $class_name - simple class name ie: session
455
     * @param mixed  $arguments
456
     * @param bool   $load_only
457
     * @param bool   $cache      whether to cache the object or not.
458
     * @return mixed
459
     */
460
    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
461
    {
462
        $paths = array(
463
            EE_LIBRARIES,
464
            EE_LIBRARIES . 'messages' . DS,
465
            EE_LIBRARIES . 'shortcodes' . DS,
466
            EE_LIBRARIES . 'qtips' . DS,
467
            EE_LIBRARIES . 'payment_methods' . DS,
468
        );
469
        // retrieve instantiated class
470
        return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
471
    }
472
473
474
475
    /**
476
     *    loads model classes - must be singletons
477
     *
478
     * @param string $class_name - simple class name ie: price
479
     * @param mixed  $arguments
480
     * @param bool   $load_only
481
     * @return EEM_Base | bool
482
     */
483
    public function load_model($class_name, $arguments = array(), $load_only = false)
484
    {
485
        $paths = apply_filters('FHEE__EE_Registry__load_model__paths', array(
486
            EE_MODELS,
487
            EE_CORE,
488
        ));
489
        // retrieve instantiated class
490
        return $this->_load($paths, 'EEM_', $class_name, 'model', $arguments, false, true, $load_only);
491
    }
492
493
494
495
    /**
496
     *    loads model classes - must be singletons
497
     *
498
     * @param string $class_name - simple class name ie: price
499
     * @param mixed  $arguments
500
     * @param bool   $load_only
501
     * @return mixed | bool
502
     */
503
    public function load_model_class($class_name, $arguments = array(), $load_only = true)
504
    {
505
        $paths = array(
506
            EE_MODELS . 'fields' . DS,
507
            EE_MODELS . 'helpers' . DS,
508
            EE_MODELS . 'relations' . DS,
509
            EE_MODELS . 'strategies' . DS,
510
        );
511
        // retrieve instantiated class
512
        return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
513
    }
514
515
516
517
    /**
518
     * Determines if $model_name is the name of an actual EE model.
519
     *
520
     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
521
     * @return boolean
522
     */
523
    public function is_model_name($model_name)
524
    {
525
        return isset($this->models[$model_name]) ? true : false;
526
    }
527
528
529
530
    /**
531
     *    generic class loader
532
     *
533
     * @param string $path_to_file - directory path to file location, not including filename
534
     * @param string $file_name    - file name  ie:  my_file.php, including extension
535
     * @param string $type         - file type - core? class? helper? model?
536
     * @param mixed  $arguments
537
     * @param bool   $load_only
538
     * @return mixed
539
     */
540
    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
541
    {
542
        // retrieve instantiated class
543
        return $this->_load($path_to_file, '', $file_name, $type, $arguments, false, true, $load_only);
544
    }
545
546
547
548
    /**
549
     *    load_addon
550
     *
551
     * @param string $path_to_file - directory path to file location, not including filename
552
     * @param string $class_name   - full class name  ie:  My_Class
553
     * @param string $type         - file type - core? class? helper? model?
554
     * @param mixed  $arguments
555
     * @param bool   $load_only
556
     * @return EE_Addon
557
     */
558
    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
559
    {
560
        // retrieve instantiated class
561
        return $this->_load($path_to_file, 'addon', $class_name, $type, $arguments, false, true, $load_only);
562
    }
563
564
565
566
    /**
567
     * instantiates, caches, and automatically resolves dependencies
568
     * for classes that use a Fully Qualified Class Name.
569
     * if the class is not capable of being loaded using PSR-4 autoloading,
570
     * then you need to use one of the existing load_*() methods
571
     * which can resolve the classname and filepath from the passed arguments
572
     *
573
     * @param bool|string $class_name   Fully Qualified Class Name
574
     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
575
     * @param bool        $cache        whether to cache the instantiated object for reuse
576
     * @param bool        $from_db      some classes are instantiated from the db
577
     *                                  and thus call a different method to instantiate
578
     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
579
     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
580
     * @return mixed                    null = failure to load or instantiate class object.
581
     *                                  object = class loaded and instantiated successfully.
582
     *                                  bool = fail or success when $load_only is true
583
     */
584
    public function create(
585
        $class_name = false,
586
        $arguments = array(),
587
        $cache = false,
588
        $from_db = false,
589
        $load_only = false,
590
        $addon = false
591
    ) {
592
        $class_name = ltrim($class_name, '\\');
593
        $class_name = $this->_dependency_map->get_alias($class_name);
594
        if ( ! class_exists($class_name)) {
595
            // maybe the class is registered with a preceding \
596
            $class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
597
            // still doesn't exist ?
598
            if ( ! class_exists($class_name)) {
599
                return null;
600
            }
601
        }
602
        // if we're only loading the class and it already exists, then let's just return true immediately
603
        if ($load_only) {
604
            return true;
605
        }
606
        $addon = $addon ? 'addon' : '';
607
        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
608
        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
609
        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
610 View Code Duplication
        if ($this->_cache_on && $cache && ! $load_only) {
611
            // return object if it's already cached
612
            $cached_class = $this->_get_cached_class($class_name, $addon);
613
            if ($cached_class !== null) {
614
                return $cached_class;
615
            }
616
        }
617
        // instantiate the requested object
618
        $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $class_obj is correct as $this->_create_object($c...ents, $addon, $from_db) (which targets EE_Registry::_create_object()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
619
        if ($this->_cache_on && $cache) {
620
            // save it for later... kinda like gum  { : $
621
            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
622
        }
623
        $this->_cache_on = true;
624
        return $class_obj;
625
    }
626
627
628
629
    /**
630
     * instantiates, caches, and injects dependencies for classes
631
     *
632
     * @param array       $file_paths   an array of paths to folders to look in
633
     * @param string      $class_prefix EE  or EEM or... ???
634
     * @param bool|string $class_name   $class name
635
     * @param string      $type         file type - core? class? helper? model?
636
     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
637
     * @param bool        $from_db      some classes are instantiated from the db
638
     *                                  and thus call a different method to instantiate
639
     * @param bool        $cache        whether to cache the instantiated object for reuse
640
     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
641
     * @return null|object|bool         null = failure to load or instantiate class object.
642
     *                                  object = class loaded and instantiated successfully.
643
     *                                  bool = fail or success when $load_only is true
644
     */
645
    protected function _load(
646
        $file_paths = array(),
647
        $class_prefix = 'EE_',
648
        $class_name = false,
649
        $type = 'class',
650
        $arguments = array(),
651
        $from_db = false,
652
        $cache = true,
653
        $load_only = false
654
    ) {
655
        $class_name = ltrim($class_name, '\\');
656
        // strip php file extension
657
        $class_name = str_replace('.php', '', trim($class_name));
658
        // does the class have a prefix ?
659
        if ( ! empty($class_prefix) && $class_prefix != 'addon') {
660
            // make sure $class_prefix is uppercase
661
            $class_prefix = strtoupper(trim($class_prefix));
662
            // add class prefix ONCE!!!
663
            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
664
        }
665
        $class_name = $this->_dependency_map->get_alias($class_name);
666
        $class_exists = class_exists($class_name);
667
        // if we're only loading the class and it already exists, then let's just return true immediately
668
        if ($load_only && $class_exists) {
669
            return true;
670
        }
671
        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
672
        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
673
        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
674 View Code Duplication
        if ($this->_cache_on && $cache && ! $load_only) {
675
            // return object if it's already cached
676
            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
677
            if ($cached_class !== null) {
678
                return $cached_class;
679
            }
680
        }
681
        // if the class doesn't already exist.. then we need to try and find the file and load it
682
        if ( ! $class_exists) {
683
            // get full path to file
684
            $path = $this->_resolve_path($class_name, $type, $file_paths);
685
            // load the file
686
            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
687
            // if loading failed, or we are only loading a file but NOT instantiating an object
688
            if ( ! $loaded || $load_only) {
689
                // return boolean if only loading, or null if an object was expected
690
                return $load_only ? $loaded : null;
691
            }
692
        }
693
        // instantiate the requested object
694
        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $class_obj is correct as $this->_create_object($c...ments, $type, $from_db) (which targets EE_Registry::_create_object()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
695
        if ($this->_cache_on && $cache) {
696
            // save it for later... kinda like gum  { : $
697
            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
698
        }
699
        $this->_cache_on = true;
700
        return $class_obj;
701
    }
702
703
704
705
    /**
706
     * _get_cached_class
707
     * attempts to find a cached version of the requested class
708
     * by looking in the following places:
709
     *        $this->{$class_abbreviation}            ie:    $this->CART
710
     *        $this->{$class_name}                        ie:    $this->Some_Class
711
     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
712
     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
713
     *
714
     * @access protected
715
     * @param string $class_name
716
     * @param string $class_prefix
717
     * @return mixed
718
     */
719
    protected function _get_cached_class($class_name, $class_prefix = '')
720
    {
721
        if ($class_name === 'EE_Registry') {
722
            return $this;
723
        }
724
        if (isset($this->_class_abbreviations[$class_name])) {
725
            $class_abbreviation = $this->_class_abbreviations[$class_name];
726
        } else {
727
            // have to specify something, but not anything that will conflict
728
            $class_abbreviation = 'FANCY_BATMAN_PANTS';
729
        }
730
        // check if class has already been loaded, and return it if it has been
731
        if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
732
            return $this->{$class_abbreviation};
733
        } else if (isset ($this->{$class_name})) {
734
            return $this->{$class_name};
735
        } else if (isset ($this->LIB->{$class_name})) {
736
            return $this->LIB->{$class_name};
737
        } else if ($class_prefix == 'addon' && isset ($this->addons->{$class_name})) {
738
            return $this->addons->{$class_name};
739
        }
740
        return null;
741
    }
742
743
744
745
    /**
746
     * _resolve_path
747
     * attempts to find a full valid filepath for the requested class.
748
     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
749
     * then returns that path if the target file has been found and is readable
750
     *
751
     * @access protected
752
     * @param string $class_name
753
     * @param string $type
754
     * @param array  $file_paths
755
     * @return string | bool
756
     */
757
    protected function _resolve_path($class_name, $type = '', $file_paths = array())
758
    {
759
        // make sure $file_paths is an array
760
        $file_paths = is_array($file_paths) ? $file_paths : array($file_paths);
761
        // cycle thru paths
762
        foreach ($file_paths as $key => $file_path) {
763
            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
764
            $file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
765
            // prep file type
766
            $type = ! empty($type) ? trim($type, '.') . '.' : '';
767
            // build full file path
768
            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
769
            //does the file exist and can be read ?
770
            if (is_readable($file_paths[$key])) {
771
                return $file_paths[$key];
772
            }
773
        }
774
        return false;
775
    }
776
777
778
779
    /**
780
     * _require_file
781
     * basically just performs a require_once()
782
     * but with some error handling
783
     *
784
     * @access protected
785
     * @param  string $path
786
     * @param  string $class_name
787
     * @param  string $type
788
     * @param  array  $file_paths
789
     * @return boolean
790
     * @throws \EE_Error
791
     */
792
    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
793
    {
794
        // don't give up! you gotta...
795
        try {
796
            //does the file exist and can it be read ?
797 View Code Duplication
            if ( ! $path) {
798
                // so sorry, can't find the file
799
                throw new EE_Error (
800
                    sprintf(
801
                        __('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', 'event_espresso'),
802
                        trim($type, '.'),
803
                        $class_name,
804
                        '<br />' . implode(',<br />', $file_paths)
805
                    )
806
                );
807
            }
808
            // get the file
809
            require_once($path);
810
            // if the class isn't already declared somewhere
811 View Code Duplication
            if (class_exists($class_name, false) === false) {
812
                // so sorry, not a class
813
                throw new EE_Error(
814
                    sprintf(
815
                        __('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
816
                        $type,
817
                        $path,
818
                        $class_name
819
                    )
820
                );
821
            }
822
        } catch (EE_Error $e) {
823
            $e->get_error();
824
            return false;
825
        }
826
        return true;
827
    }
828
829
830
831
    /**
832
     * _create_object
833
     * Attempts to instantiate the requested class via any of the
834
     * commonly used instantiation methods employed throughout EE.
835
     * The priority for instantiation is as follows:
836
     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
837
     *        - model objects via their 'new_instance_from_db' method
838
     *        - model objects via their 'new_instance' method
839
     *        - "singleton" classes" via their 'instance' method
840
     *    - standard instantiable classes via their __constructor
841
     * Prior to instantiation, if the classname exists in the dependency_map,
842
     * then the constructor for the requested class will be examined to determine
843
     * if any dependencies exist, and if they can be injected.
844
     * If so, then those classes will be added to the array of arguments passed to the constructor
845
     *
846
     * @access protected
847
     * @param string $class_name
848
     * @param array  $arguments
849
     * @param string $type
850
     * @param bool   $from_db
851
     * @return null | object
852
     * @throws \EE_Error
853
     */
854
    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
855
    {
856
        $class_obj = null;
857
        $instantiation_mode = '0) none';
858
        // don't give up! you gotta...
859
        try {
860
            // create reflection
861
            $reflector = $this->get_ReflectionClass($class_name);
862
            // make sure arguments are an array
863
            $arguments = is_array($arguments) ? $arguments : array($arguments);
864
            // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
865
            // else wrap it in an additional array so that it doesn't get split into multiple parameters
866
            $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
867
                ? $arguments
868
                : array($arguments);
869
            // attempt to inject dependencies ?
870
            if ($this->_dependency_map->has($class_name)) {
871
                $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
872
            }
873
            // instantiate the class if possible
874
            if ($reflector->isAbstract()) {
875
                // nothing to instantiate, loading file was enough
876
                // does not throw an exception so $instantiation_mode is unused
877
                // $instantiation_mode = "1) no constructor abstract class";
878
                $class_obj = true;
879
            } else if ($reflector->getConstructor() === null && $reflector->isInstantiable() && empty($arguments)) {
880
                // no constructor = static methods only... nothing to instantiate, loading file was enough
881
                $instantiation_mode = "2) no constructor but instantiable";
882
                $class_obj = $reflector->newInstance();
883
            } else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
884
                $instantiation_mode = "3) new_instance_from_db()";
885
                $class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
886
            } else if (method_exists($class_name, 'new_instance')) {
887
                $instantiation_mode = "4) new_instance()";
888
                $class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
889
            } else if (method_exists($class_name, 'instance')) {
890
                $instantiation_mode = "5) instance()";
891
                $class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
892
            } else if ($reflector->isInstantiable()) {
893
                $instantiation_mode = "6) constructor";
894
                $class_obj = $reflector->newInstanceArgs($arguments);
895
            } else {
896
                // heh ? something's not right !
897
                throw new EE_Error(
898
                    sprintf(
899
                        __('The %s file %s could not be instantiated.', 'event_espresso'),
900
                        $type,
901
                        $class_name
902
                    )
903
                );
904
            }
905
        } catch (Exception $e) {
906
            if ( ! $e instanceof EE_Error) {
907
                $e = new EE_Error(
908
                    sprintf(
909
                        __('The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s', 'event_espresso'),
910
                        $class_name,
911
                        '<br />',
912
                        $e->getMessage(),
913
                        $instantiation_mode
914
                    )
915
                );
916
            }
917
            $e->get_error();
918
        }
919
        return $class_obj;
920
    }
921
922
923
924
    /**
925
     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
926
     * @param array $array
927
     * @return bool
928
     */
929
    protected function _array_is_numerically_and_sequentially_indexed(array $array)
930
    {
931
        return ! empty($array) ? array_keys($array) === range(0, count($array) - 1) : true;
932
    }
933
934
935
936
    /**
937
     * getReflectionClass
938
     * checks if a ReflectionClass object has already been generated for a class
939
     * and returns that instead of creating a new one
940
     *
941
     * @access public
942
     * @param string $class_name
943
     * @return ReflectionClass
944
     */
945 View Code Duplication
    public function get_ReflectionClass($class_name)
946
    {
947
        if (
948
            ! isset($this->_reflectors[$class_name])
949
            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
950
        ) {
951
            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
952
        }
953
        return $this->_reflectors[$class_name];
954
    }
955
956
957
958
    /**
959
     * _resolve_dependencies
960
     * examines the constructor for the requested class to determine
961
     * if any dependencies exist, and if they can be injected.
962
     * If so, then those classes will be added to the array of arguments passed to the constructor
963
     * PLZ NOTE: this is achieved by type hinting the constructor params
964
     * For example:
965
     *        if attempting to load a class "Foo" with the following constructor:
966
     *        __construct( Bar $bar_class, Fighter $grohl_class )
967
     *        then $bar_class and $grohl_class will be added to the $arguments array,
968
     *        but only IF they are NOT already present in the incoming arguments array,
969
     *        and the correct classes can be loaded
970
     *
971
     * @access protected
972
     * @param ReflectionClass $reflector
973
     * @param string          $class_name
974
     * @param array           $arguments
975
     * @return array
976
     * @throws \ReflectionException
977
     */
978
    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
979
    {
980
        // let's examine the constructor
981
        $constructor = $reflector->getConstructor();
982
        // whu? huh? nothing?
983
        if ( ! $constructor) {
984
            return $arguments;
985
        }
986
        // get constructor parameters
987
        $params = $constructor->getParameters();
988
        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
989
        $argument_keys = array_keys($arguments);
990
        // now loop thru all of the constructors expected parameters
991
        foreach ($params as $index => $param) {
992
            // is this a dependency for a specific class ?
993
            $param_class = $param->getClass() ? $param->getClass()->name : null;
994
            if (
995
                // param is not even a class
996
                empty($param_class)
997
                // and something already exists in the incoming arguments for this param
998
                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
999
            ) {
1000
                // so let's skip this argument and move on to the next
1001
                continue;
1002
            } else if (
1003
                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1004
                ! empty($param_class)
1005
                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1006
                && $arguments[$argument_keys[$index]] instanceof $param_class
1007
            ) {
1008
                // skip this argument and move on to the next
1009
                continue;
1010
            } else if (
1011
                // parameter is type hinted as a class, and should be injected
1012
                ! empty($param_class)
1013
                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1014
            ) {
1015
                $arguments = $this->_resolve_dependency($class_name, $param_class, $arguments, $index);
1016
            } else {
1017
                try {
1018
                    $arguments[$index] = $param->getDefaultValue();
1019
                } catch (ReflectionException $e) {
1020
                    throw new ReflectionException(
1021
                        sprintf(
1022
                            __('%1$s for parameter "$%2$s"', 'event_espresso'),
1023
                            $e->getMessage(),
1024
                            $param->getName()
1025
                        )
1026
                    );
1027
                }
1028
            }
1029
        }
1030
        return $arguments;
1031
    }
1032
1033
1034
1035
    /**
1036
     * @access protected
1037
     * @param string $class_name
1038
     * @param string $param_class
1039
     * @param array  $arguments
1040
     * @param mixed  $index
1041
     * @return array
1042
     */
1043
    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1044
    {
1045
        $dependency = null;
1046
        // should dependency be loaded from cache ?
1047
        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency($class_name, $param_class)
1048
                    !== EE_Dependency_Map::load_new_object
1049
            ? true
1050
            : false;
1051
        // we might have a dependency...
1052
        // let's MAYBE try and find it in our cache if that's what's been requested
1053
        $cached_class = $cache_on ? $this->_get_cached_class($param_class) : null;
1054
        // and grab it if it exists
1055
        if ($cached_class instanceof $param_class) {
1056
            $dependency = $cached_class;
1057
        } else if ($param_class != $class_name) {
1058
            // obtain the loader method from the dependency map
1059
            $loader = $this->_dependency_map->class_loader($param_class);
1060
            // is loader a custom closure ?
1061
            if ($loader instanceof Closure) {
1062
                $dependency = $loader();
1063
            } else {
1064
                // set the cache on property for the recursive loading call
1065
                $this->_cache_on = $cache_on;
1066
                // if not, then let's try and load it via the registry
1067
                if (method_exists($this, $loader)) {
1068
                    $dependency = $this->{$loader}($param_class);
1069
                } else {
1070
                    $dependency = $this->create($param_class, array(), $cache_on);
1071
                }
1072
            }
1073
        }
1074
        // did we successfully find the correct dependency ?
1075
        if ($dependency instanceof $param_class) {
1076
            // then let's inject it into the incoming array of arguments at the correct location
1077
            if (isset($argument_keys[$index])) {
0 ignored issues
show
Bug introduced by
The variable $argument_keys seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
1078
                $arguments[$argument_keys[$index]] = $dependency;
1079
            } else {
1080
                $arguments[$index] = $dependency;
1081
            }
1082
        }
1083
        return $arguments;
1084
    }
1085
1086
1087
1088
    /**
1089
     * _set_cached_class
1090
     * attempts to cache the instantiated class locally
1091
     * in one of the following places, in the following order:
1092
     *        $this->{class_abbreviation}   ie:    $this->CART
1093
     *        $this->{$class_name}          ie:    $this->Some_Class
1094
     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1095
     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1096
     *
1097
     * @access protected
1098
     * @param object $class_obj
1099
     * @param string $class_name
1100
     * @param string $class_prefix
1101
     * @param bool   $from_db
1102
     * @return void
1103
     */
1104
    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1105
    {
1106
        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1107
            return;
1108
        }
1109
        // return newly instantiated class
1110
        if (isset($this->_class_abbreviations[$class_name])) {
1111
            $class_abbreviation = $this->_class_abbreviations[$class_name];
1112
            $this->{$class_abbreviation} = $class_obj;
1113
        } else if (property_exists($this, $class_name)) {
1114
            $this->{$class_name} = $class_obj;
1115
        } else if ($class_prefix == 'addon') {
1116
            $this->addons->{$class_name} = $class_obj;
1117
        } else if ( ! $from_db) {
1118
            $this->LIB->{$class_name} = $class_obj;
1119
        }
1120
    }
1121
1122
1123
1124
    /**
1125
     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1126
     *
1127
     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1128
     *                          in the EE_Dependency_Map::$_class_loaders array,
1129
     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1130
     * @param array  $arguments
1131
     * @return object
1132
     */
1133
    public static function factory($classname, $arguments = array())
1134
    {
1135
        $loader = self::instance()->_dependency_map->class_loader($classname);
1136
        if ($loader instanceof Closure) {
1137
            return $loader($arguments);
1138
        } else if (method_exists(EE_Registry::instance(), $loader)) {
1139
            return EE_Registry::instance()->{$loader}($classname, $arguments);
1140
        }
1141
        return null;
1142
    }
1143
1144
1145
1146
    /**
1147
     * Gets the addon by its name/slug (not classname. For that, just
1148
     * use the classname as the property name on EE_Config::instance()->addons)
1149
     *
1150
     * @param string $name
1151
     * @return EE_Addon
1152
     */
1153
    public function get_addon_by_name($name)
1154
    {
1155
        foreach ($this->addons as $addon) {
1156
            if ($addon->name() == $name) {
1157
                return $addon;
1158
            }
1159
        }
1160
        return null;
1161
    }
1162
1163
1164
1165
    /**
1166
     * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their name() function) They're already available on EE_Config::instance()->addons as properties, where each property's name is
1167
     * the addon's classname. So if you just want to get the addon by classname, use EE_Config::instance()->addons->{classname}
1168
     *
1169
     * @return EE_Addon[] where the KEYS are the addon's name()
1170
     */
1171
    public function get_addons_by_name()
1172
    {
1173
        $addons = array();
1174
        foreach ($this->addons as $addon) {
1175
            $addons[$addon->name()] = $addon;
1176
        }
1177
        return $addons;
1178
    }
1179
1180
1181
1182
    /**
1183
     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1184
     * a stale copy of it around
1185
     *
1186
     * @param string $model_name
1187
     * @return \EEM_Base
1188
     * @throws \EE_Error
1189
     */
1190
    public function reset_model($model_name)
1191
    {
1192
        $model_class_name = strpos($model_name, 'EEM_') !== 0 ? "EEM_{$model_name}" : $model_name;
1193
        if ( ! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1194
            return null;
1195
        }
1196
        //get that model reset it and make sure we nuke the old reference to it
1197
        if ($this->LIB->{$model_class_name} instanceof $model_class_name && is_callable(array($model_class_name, 'reset'))) {
1198
            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1199
        } else {
1200
            throw new EE_Error(sprintf(__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1201
        }
1202
        return $this->LIB->{$model_class_name};
1203
    }
1204
1205
1206
1207
    /**
1208
     * Resets the registry.
1209
     * The criteria for what gets reset is based on what can be shared between sites on the same request when switch_to_blog
1210
     * is used in a multisite install.  Here is a list of things that are NOT reset.
1211
     * - $_dependency_map
1212
     * - $_class_abbreviations
1213
     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1214
     * - $REQ:  Still on the same request so no need to change.
1215
     * - $CAP: There is no site specific state in the EE_Capability class.
1216
     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only one Session
1217
     *         can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1218
     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1219
     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1220
     *             switch or on the restore.
1221
     * - $modules
1222
     * - $shortcodes
1223
     * - $widgets
1224
     *
1225
     * @param boolean $hard             whether to reset data in the database too, or just refresh
1226
     *                                  the Registry to its state at the beginning of the request
1227
     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1228
     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not sure if you CAN
1229
     *                                  currently reinstantiate the singletons at the moment)
1230
     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so client
1231
     *                                  code instead can just change the model context to a different blog id if necessary
1232
     * @return EE_Registry
1233
     */
1234
    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1235
    {
1236
        $instance = self::instance();
1237
        $instance->_cache_on = true;
1238
        // reset some "special" classes
1239
        EEH_Activation::reset();
1240
        $instance->CFG = $instance->CFG->reset($hard, $reinstantiate);
1241
        $instance->CART = null;
1242
        $instance->MRM = null;
1243
        $instance->AssetsRegistry = null;
1244
        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1245
        //messages reset
1246
        EED_Messages::reset();
1247
        //handle of objects cached on LIB
1248
        foreach (array('LIB', 'modules', 'shortcodes') as $cache) {
1249
            foreach ($instance->{$cache} as $class_name => $class) {
1250
                if (EE_Registry::_reset_and_unset_object($class, $reset_models)) {
1251
                    unset($instance->{$cache}->{$class_name});
1252
                }
1253
            }
1254
        }
1255
        return $instance;
1256
    }
1257
1258
1259
1260
    /**
1261
     * if passed object implements ResettableInterface, then call it's reset() method
1262
     * if passed object implements InterminableInterface, then return false,
1263
     * to indicate that it should NOT be cleared from the Registry cache
1264
     *
1265
     * @param      $object
1266
     * @param bool $reset_models
1267
     * @return bool returns true if cached object should be unset
1268
     */
1269
    private static function _reset_and_unset_object($object, $reset_models)
1270
    {
1271
        static $count = 0;
1272
        $count++;
1273
        if ($object instanceof ResettableInterface) {
1274
            if ($object instanceof EEM_Base) {
1275
                if ($reset_models) {
1276
                    $object->reset();
1277
                    return true;
1278
                }
1279
                return false;
1280
            }
1281
            $object->reset();
1282
            return true;
1283
        }
1284
        if ( ! $object instanceof InterminableInterface) {
1285
            return true;
1286
        }
1287
        return false;
1288
    }
1289
1290
1291
1292
    /**
1293
     * @override magic methods
1294
     * @return void
1295
     */
1296
    public final function __destruct()
1297
    {
1298
    }
1299
1300
1301
1302
    /**
1303
     * @param $a
1304
     * @param $b
1305
     */
1306
    public final function __call($a, $b)
1307
    {
1308
    }
1309
1310
1311
1312
    /**
1313
     * @param $a
1314
     */
1315
    public final function __get($a)
1316
    {
1317
    }
1318
1319
1320
1321
    /**
1322
     * @param $a
1323
     * @param $b
1324
     */
1325
    public final function __set($a, $b)
1326
    {
1327
    }
1328
1329
1330
1331
    /**
1332
     * @param $a
1333
     */
1334
    public final function __isset($a)
1335
    {
1336
    }
1337
1338
1339
1340
    /**
1341
     * @param $a
1342
     */
1343
    public final function __unset($a)
1344
    {
1345
    }
1346
1347
1348
1349
    /**
1350
     * @return array
1351
     */
1352
    public final function __sleep()
1353
    {
1354
        return array();
1355
    }
1356
1357
1358
1359
    public final function __wakeup()
1360
    {
1361
    }
1362
1363
1364
1365
    /**
1366
     * @return string
1367
     */
1368
    public final function __toString()
1369
    {
1370
        return '';
1371
    }
1372
1373
1374
1375
    public final function __invoke()
1376
    {
1377
    }
1378
1379
1380
1381
    public final static function __set_state($array = array())
1382
    {
1383
        return EE_Registry::instance();
1384
    }
1385
1386
1387
1388
    public final function __clone()
1389
    {
1390
    }
1391
1392
1393
1394
    /**
1395
     * @param $a
1396
     * @param $b
1397
     */
1398
    public final static function __callStatic($a, $b)
1399
    {
1400
    }
1401
1402
1403
1404
    /**
1405
     * Gets all the custom post type models defined
1406
     *
1407
     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1408
     */
1409
    public function cpt_models()
1410
    {
1411
        $cpt_models = array();
1412
        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1413
            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1414
                $cpt_models[$short_name] = $classname;
1415
            }
1416
        }
1417
        return $cpt_models;
1418
    }
1419
1420
1421
1422
    /**
1423
     * @return \EE_Config
1424
     */
1425
    public static function CFG()
1426
    {
1427
        return self::instance()->CFG;
1428
    }
1429
1430
1431
}
1432
// End of file EE_Registry.core.php
1433
// Location: ./core/EE_Registry.core.php
1434