Completed
Branch FET-10768-extract-admin-bar (2dd98c)
by
unknown
146:19 queued 134:18
created

EE_Registry::loadOrVerifyClassExists()   D

Complexity

Conditions 9
Paths 7

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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