Completed
Branch BUG-10846-ticket-selector-ajax (55c860)
by
unknown
32:44 queued 21:54
created

EE_Registry::__call()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

function notNullable(stdClass $x) { }

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

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

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