Completed
Branch FET-10766-extract-activation-d... (2c1e01)
by
unknown
104:24 queued 93:14
created

EE_Registry::reset_model()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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