Completed
Branch BUG-10738-inconsistency-in-ses... (cda363)
by
unknown
13:38 queued 12s
created

EE_Registry::_load()   C

Complexity

Conditions 15
Paths 28

Size

Total Lines 59
Code Lines 34

Duplication

Lines 7
Ratio 11.86 %

Importance

Changes 0
Metric Value
cc 15
eloc 34
c 0
b 0
f 0
nc 28
nop 8
dl 7
loc 59
rs 6.3845

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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