Completed
Branch FET-9222-rest-api-writes (9a0487)
by
unknown
71:42 queued 58:38
created

EE_Registry::_load()   C

Complexity

Conditions 15
Paths 28

Size

Total Lines 59
Code Lines 34

Duplication

Lines 7
Ratio 11.86 %

Importance

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

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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

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

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

function notNullable(stdClass $x) { }

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

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

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