Completed
Branch Gutenberg/event-attendees-bloc... (e27df5)
by
unknown
56:20 queued 41:53
created

EE_System   F

Complexity

Total Complexity 142

Size/Duplication

Total Lines 1274
Duplicated Lines 1.49 %

Coupling/Cohesion

Components 1
Dependencies 26

Importance

Changes 0
Metric Value
dl 19
loc 1274
rs 0.5217
c 0
b 0
f 0
wmc 142
lcom 1
cbo 26

41 Methods

Rating   Name   Duplication   Size   Complexity  
A reset() 0 11 1
A detect_activations_or_upgrades() 0 11 3
B _deactivate_incompatible_addons() 0 15 5
A do_not_cache() 0 19 4
A set_hooks_for_core() 0 9 1
A remove_pages_from_wp_list_pages() 0 4 1
A extra_nocache_headers() 0 8 1
A addEspressoToolbar() 0 7 1
A nocache_headers() 0 4 1
A instance() 0 12 2
A __construct() 0 69 1
A loadCapabilities() 0 10 1
A loadCommandBus() 0 16 1
A loadPluginApi() 0 7 1
B deactivateIncompatibleAddon() 0 34 5
B load_espresso_addons() 0 35 5
B detect_if_activation_or_upgrade() 0 34 6
A _handle_core_version_change() 0 9 1
C fix_espresso_db_upgrade_option() 0 39 7
C initialize_db_if_no_migrations_required() 0 31 8
A initialize_addons() 0 9 3
A update_list_of_installed_versions() 0 12 3
A detect_req_type() 0 16 3
A _detect_major_version_change() 0 10 3
A is_major_version_change() 0 4 1
C detect_req_type_given_activation_history() 19 48 9
A _new_version_is_higher() 0 7 1
D _get_most_recently_active_version_from_activation_history() 0 28 9
B redirect_to_about_ee() 0 23 6
B load_core_configuration() 0 29 3
B _parse_model_names() 0 22 4
A _maybe_brew_regular() 0 16 2
B _incompatible_addon_error() 0 32 4
A brew_espresso() 0 18 3
A perform_activations_upgrades_and_migrations() 0 4 1
A load_CPTs_and_session() 0 22 1
B load_controllers() 0 15 6
B register_shortcodes_modules_and_widgets() 0 22 5
C core_loaded_and_ready() 0 34 14
A initialize() 0 4 1
A initialize_last() 0 15 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EE_System often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EE_System, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
use EventEspresso\core\domain\Domain;
4
use EventEspresso\core\domain\DomainFactory;
5
use EventEspresso\core\domain\services\contexts\RequestTypeContextCheckerInterface;
6
use EventEspresso\core\domain\values\FilePath;
7
use EventEspresso\core\domain\values\FullyQualifiedName;
8
use EventEspresso\core\domain\values\Version;
9
use EventEspresso\core\exceptions\ExceptionStackTraceDisplay;
10
use EventEspresso\core\exceptions\InvalidClassException;
11
use EventEspresso\core\exceptions\InvalidDataTypeException;
12
use EventEspresso\core\exceptions\InvalidFilePathException;
13
use EventEspresso\core\exceptions\InvalidInterfaceException;
14
use EventEspresso\core\interfaces\ResettableInterface;
15
use EventEspresso\core\services\loaders\LoaderFactory;
16
use EventEspresso\core\services\loaders\LoaderInterface;
17
use EventEspresso\core\services\request\RequestInterface;
18
19
/**
20
 * EE_System
21
 * The backbone of the core application that the rest of the system builds off of once bootstrapping is complete
22
 *
23
 * @package        Event Espresso
24
 * @subpackage     core/
25
 * @author         Brent Christensen, Michael Nelson
26
 */
27
final class EE_System implements ResettableInterface
28
{
29
30
    /**
31
     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
     */
34
    const req_type_normal = 0;
35
36
    /**
37
     * Indicates this is a brand new installation of EE so we should install
38
     * tables and default data etc
39
     */
40
    const req_type_new_activation = 1;
41
42
    /**
43
     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
     * and we just exited maintenance mode). We MUST check the database is setup properly
45
     * and that default data is setup too
46
     */
47
    const req_type_reactivation = 2;
48
49
    /**
50
     * indicates that EE has been upgraded since its previous request.
51
     * We may have data migration scripts to call and will want to trigger maintenance mode
52
     */
53
    const req_type_upgrade = 3;
54
55
    /**
56
     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
     */
58
    const req_type_downgrade = 4;
59
60
    /**
61
     * @deprecated since version 4.6.0.dev.006
62
     * Now whenever a new_activation is detected the request type is still just
63
     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
     * (Specifically, when the migration manager indicates migrations are finished
67
     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
     */
69
    const req_type_activation_but_not_installed = 5;
70
71
    /**
72
     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
     */
74
    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
76
    /**
77
     * @var EE_System $_instance
78
     */
79
    private static $_instance;
80
81
    /**
82
     * @var EE_Registry $registry
83
     */
84
    private $registry;
85
86
    /**
87
     * @var LoaderInterface $loader
88
     */
89
    private $loader;
90
91
    /**
92
     * @var EE_Capabilities $capabilities
93
     */
94
    private $capabilities;
95
96
    /**
97
     * @var RequestInterface $request
98
     */
99
    private $request;
100
101
    /**
102
     * @var EE_Maintenance_Mode $maintenance_mode
103
     */
104
    private $maintenance_mode;
105
106
    /**
107
     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
     *
110
     * @var int $_req_type
111
     */
112
    private $_req_type;
113
114
    /**
115
     * Whether or not there was a non-micro version change in EE core version during this request
116
     *
117
     * @var boolean $_major_version_change
118
     */
119
    private $_major_version_change = false;
120
121
    /**
122
     * A Context DTO dedicated solely to identifying the current request type.
123
     *
124
     * @var RequestTypeContextCheckerInterface $request_type
125
     */
126
    private $request_type;
0 ignored issues
show
Unused Code introduced by
The property $request_type is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
127
128
129
    /**
130
     * @singleton method used to instantiate class object
131
     * @param EE_Registry|null         $registry
132
     * @param LoaderInterface|null     $loader
133
     * @param RequestInterface|null    $request
134
     * @param EE_Maintenance_Mode|null $maintenance_mode
135
     * @return EE_System
136
     */
137
    public static function instance(
138
        EE_Registry $registry = null,
139
        LoaderInterface $loader = null,
140
        RequestInterface $request = null,
141
        EE_Maintenance_Mode $maintenance_mode = null
142
    ) {
143
        // check if class object is instantiated
144
        if (! self::$_instance instanceof EE_System) {
145
            self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
0 ignored issues
show
Bug introduced by
It seems like $registry defined by parameter $registry on line 138 can be null; however, EE_System::__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...
Bug introduced by
It seems like $loader defined by parameter $loader on line 139 can be null; however, EE_System::__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...
Bug introduced by
It seems like $request defined by parameter $request on line 140 can be null; however, EE_System::__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...
Bug introduced by
It seems like $maintenance_mode defined by parameter $maintenance_mode on line 141 can be null; however, EE_System::__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...
146
        }
147
        return self::$_instance;
148
    }
149
150
151
    /**
152
     * resets the instance and returns it
153
     *
154
     * @return EE_System
155
     */
156
    public static function reset()
157
    {
158
        self::$_instance->_req_type = null;
159
        // make sure none of the old hooks are left hanging around
160
        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
        // we need to reset the migration manager in order for it to detect DMSs properly
162
        EE_Data_Migration_Manager::reset();
163
        self::instance()->detect_activations_or_upgrades();
164
        self::instance()->perform_activations_upgrades_and_migrations();
165
        return self::instance();
166
    }
167
168
169
    /**
170
     * sets hooks for running rest of system
171
     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
     * starting EE Addons from any other point may lead to problems
173
     *
174
     * @param EE_Registry         $registry
175
     * @param LoaderInterface     $loader
176
     * @param RequestInterface    $request
177
     * @param EE_Maintenance_Mode $maintenance_mode
178
     */
179
    private function __construct(
180
        EE_Registry $registry,
181
        LoaderInterface $loader,
182
        RequestInterface $request,
183
        EE_Maintenance_Mode $maintenance_mode
184
    ) {
185
        $this->registry = $registry;
186
        $this->loader = $loader;
187
        $this->request = $request;
188
        $this->maintenance_mode = $maintenance_mode;
189
        do_action('AHEE__EE_System__construct__begin', $this);
190
        add_action(
191
            'AHEE__EE_Bootstrap__load_espresso_addons',
192
            array($this, 'loadCapabilities'),
193
            5
194
        );
195
        add_action(
196
            'AHEE__EE_Bootstrap__load_espresso_addons',
197
            array($this, 'loadCommandBus'),
198
            7
199
        );
200
        add_action(
201
            'AHEE__EE_Bootstrap__load_espresso_addons',
202
            array($this, 'loadPluginApi'),
203
            9
204
        );
205
        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
206
        add_action(
207
            'AHEE__EE_Bootstrap__load_espresso_addons',
208
            array($this, 'load_espresso_addons')
209
        );
210
        // when an ee addon is activated, we want to call the core hook(s) again
211
        // because the newly-activated addon didn't get a chance to run at all
212
        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
213
        // detect whether install or upgrade
214
        add_action(
215
            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
216
            array($this, 'detect_activations_or_upgrades'),
217
            3
218
        );
219
        // load EE_Config, EE_Textdomain, etc
220
        add_action(
221
            'AHEE__EE_Bootstrap__load_core_configuration',
222
            array($this, 'load_core_configuration'),
223
            5
224
        );
225
        // load EE_Config, EE_Textdomain, etc
226
        add_action(
227
            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
228
            array($this, 'register_shortcodes_modules_and_widgets'),
229
            7
230
        );
231
        // you wanna get going? I wanna get going... let's get going!
232
        add_action(
233
            'AHEE__EE_Bootstrap__brew_espresso',
234
            array($this, 'brew_espresso'),
235
            9
236
        );
237
        // other housekeeping
238
        // exclude EE critical pages from wp_list_pages
239
        add_filter(
240
            'wp_list_pages_excludes',
241
            array($this, 'remove_pages_from_wp_list_pages'),
242
            10
243
        );
244
        // ALL EE Addons should use the following hook point to attach their initial setup too
245
        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
246
        do_action('AHEE__EE_System__construct__complete', $this);
247
    }
248
249
250
    /**
251
     * load and setup EE_Capabilities
252
     *
253
     * @return void
254
     * @throws EE_Error
255
     */
256
    public function loadCapabilities()
257
    {
258
        $this->capabilities = $this->loader->getShared('EE_Capabilities');
259
        add_action(
260
            'AHEE__EE_Capabilities__init_caps__before_initialization',
261
            function () {
262
                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
263
            }
264
        );
265
    }
266
267
268
    /**
269
     * create and cache the CommandBus, and also add middleware
270
     * The CapChecker middleware requires the use of EE_Capabilities
271
     * which is why we need to load the CommandBus after Caps are set up
272
     *
273
     * @return void
274
     * @throws EE_Error
275
     */
276
    public function loadCommandBus()
277
    {
278
        $this->loader->getShared(
279
            'CommandBusInterface',
280
            array(
281
                null,
282
                apply_filters(
283
                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
284
                    array(
285
                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
286
                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
287
                    )
288
                ),
289
            )
290
        );
291
    }
292
293
294
    /**
295
     * @return void
296
     * @throws EE_Error
297
     */
298
    public function loadPluginApi()
299
    {
300
        // set autoloaders for all of the classes implementing EEI_Plugin_API
301
        // which provide helpers for EE plugin authors to more easily register certain components with EE.
302
        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
303
        $this->loader->getShared('EE_Request_Handler');
304
    }
305
306
307
    /**
308
     * @param string $addon_name
309
     * @param string $version_constant
310
     * @param string $min_version_required
311
     * @param string $load_callback
312
     * @param string $plugin_file_constant
313
     * @return void
314
     */
315
    private function deactivateIncompatibleAddon(
316
        $addon_name,
317
        $version_constant,
318
        $min_version_required,
319
        $load_callback,
320
        $plugin_file_constant
321
    ) {
322
        if (! defined($version_constant)) {
323
            return;
324
        }
325
        $addon_version = constant($version_constant);
326
        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
327
            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
328
            if (! function_exists('deactivate_plugins')) {
329
                require_once ABSPATH . 'wp-admin/includes/plugin.php';
330
            }
331
            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
332
            unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
333
            EE_Error::add_error(
334
                sprintf(
335
                    esc_html__(
336
                        'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
337
                        'event_espresso'
338
                    ),
339
                    $addon_name,
340
                    $min_version_required
341
                ),
342
                __FILE__,
343
                __FUNCTION__ . "({$addon_name})",
344
                __LINE__
345
            );
346
            EE_Error::get_notices(false, true);
347
        }
348
    }
349
350
351
    /**
352
     * load_espresso_addons
353
     * allow addons to load first so that they can set hooks for running DMS's, etc
354
     * this is hooked into both:
355
     *    'AHEE__EE_Bootstrap__load_core_configuration'
356
     *        which runs during the WP 'plugins_loaded' action at priority 5
357
     *    and the WP 'activate_plugin' hook point
358
     *
359
     * @access public
360
     * @return void
361
     */
362
    public function load_espresso_addons()
363
    {
364
        $this->deactivateIncompatibleAddon(
365
            'Wait Lists',
366
            'EE_WAIT_LISTS_VERSION',
367
            '1.0.0.beta.074',
368
            'load_espresso_wait_lists',
369
            'EE_WAIT_LISTS_PLUGIN_FILE'
370
        );
371
        $this->deactivateIncompatibleAddon(
372
            'Automated Upcoming Event Notifications',
373
            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
374
            '1.0.0.beta.091',
375
            'load_espresso_automated_upcoming_event_notification',
376
            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
377
        );
378
        do_action('AHEE__EE_System__load_espresso_addons');
379
        // if the WP API basic auth plugin isn't already loaded, load it now.
380
        // We want it for mobile apps. Just include the entire plugin
381
        // also, don't load the basic auth when a plugin is getting activated, because
382
        // it could be the basic auth plugin, and it doesn't check if its methods are already defined
383
        // and causes a fatal error
384
        if ($this->request->getRequestParam('activate') !== 'true'
385
            && ! function_exists('json_basic_auth_handler')
386
            && ! function_exists('json_basic_auth_error')
387
            && ! in_array(
388
                $this->request->getRequestParam('action'),
389
                array('activate', 'activate-selected'),
390
                true
391
            )
392
        ) {
393
            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
394
        }
395
        do_action('AHEE__EE_System__load_espresso_addons__complete');
396
    }
397
398
399
    /**
400
     * detect_activations_or_upgrades
401
     * Checks for activation or upgrade of core first;
402
     * then also checks if any registered addons have been activated or upgraded
403
     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
404
     * which runs during the WP 'plugins_loaded' action at priority 3
405
     *
406
     * @access public
407
     * @return void
408
     */
409
    public function detect_activations_or_upgrades()
410
    {
411
        // first off: let's make sure to handle core
412
        $this->detect_if_activation_or_upgrade();
413
        foreach ($this->registry->addons as $addon) {
414
            if ($addon instanceof EE_Addon) {
415
                // detect teh request type for that addon
416
                $addon->detect_activation_or_upgrade();
417
            }
418
        }
419
    }
420
421
422
    /**
423
     * detect_if_activation_or_upgrade
424
     * Takes care of detecting whether this is a brand new install or code upgrade,
425
     * and either setting up the DB or setting up maintenance mode etc.
426
     *
427
     * @access public
428
     * @return void
429
     */
430
    public function detect_if_activation_or_upgrade()
431
    {
432
        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
433
        // check if db has been updated, or if its a brand-new installation
434
        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
435
        $request_type = $this->detect_req_type($espresso_db_update);
436
        // EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
437
        switch ($request_type) {
438
            case EE_System::req_type_new_activation:
439
                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
440
                $this->_handle_core_version_change($espresso_db_update);
441
                break;
442
            case EE_System::req_type_reactivation:
443
                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
444
                $this->_handle_core_version_change($espresso_db_update);
445
                break;
446
            case EE_System::req_type_upgrade:
447
                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
448
                // migrations may be required now that we've upgraded
449
                $this->maintenance_mode->set_maintenance_mode_if_db_old();
450
                $this->_handle_core_version_change($espresso_db_update);
451
                break;
452
            case EE_System::req_type_downgrade:
453
                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
454
                // its possible migrations are no longer required
455
                $this->maintenance_mode->set_maintenance_mode_if_db_old();
456
                $this->_handle_core_version_change($espresso_db_update);
457
                break;
458
            case EE_System::req_type_normal:
459
            default:
460
                break;
461
        }
462
        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
463
    }
464
465
466
    /**
467
     * Updates the list of installed versions and sets hooks for
468
     * initializing the database later during the request
469
     *
470
     * @param array $espresso_db_update
471
     */
472
    private function _handle_core_version_change($espresso_db_update)
473
    {
474
        $this->update_list_of_installed_versions($espresso_db_update);
475
        // get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
476
        add_action(
477
            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
478
            array($this, 'initialize_db_if_no_migrations_required')
479
        );
480
    }
481
482
483
    /**
484
     * standardizes the wp option 'espresso_db_upgrade' which actually stores
485
     * information about what versions of EE have been installed and activated,
486
     * NOT necessarily the state of the database
487
     *
488
     * @param mixed $espresso_db_update           the value of the WordPress option.
489
     *                                            If not supplied, fetches it from the options table
490
     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
491
     */
492
    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
493
    {
494
        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
495
        if (! $espresso_db_update) {
496
            $espresso_db_update = get_option('espresso_db_update');
497
        }
498
        // check that option is an array
499
        if (! is_array($espresso_db_update)) {
500
            // if option is FALSE, then it never existed
501
            if ($espresso_db_update === false) {
502
                // make $espresso_db_update an array and save option with autoload OFF
503
                $espresso_db_update = array();
504
                add_option('espresso_db_update', $espresso_db_update, '', 'no');
505
            } else {
506
                // option is NOT FALSE but also is NOT an array, so make it an array and save it
507
                $espresso_db_update = array($espresso_db_update => array());
508
                update_option('espresso_db_update', $espresso_db_update);
509
            }
510
        } else {
511
            $corrected_db_update = array();
512
            // if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
513
            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
514
                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
515
                    // the key is an int, and the value IS NOT an array
516
                    // so it must be numerically-indexed, where values are versions installed...
517
                    // fix it!
518
                    $version_string = $should_be_array;
519
                    $corrected_db_update[ $version_string ] = array('unknown-date');
520
                } else {
521
                    // ok it checks out
522
                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
523
                }
524
            }
525
            $espresso_db_update = $corrected_db_update;
526
            update_option('espresso_db_update', $espresso_db_update);
527
        }
528
        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
529
        return $espresso_db_update;
530
    }
531
532
533
    /**
534
     * Does the traditional work of setting up the plugin's database and adding default data.
535
     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
536
     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
537
     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
538
     * so that it will be done when migrations are finished
539
     *
540
     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
541
     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
542
     *                                       This is a resource-intensive job
543
     *                                       so we prefer to only do it when necessary
544
     * @return void
545
     * @throws EE_Error
546
     */
547
    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
548
    {
549
        $request_type = $this->detect_req_type();
550
        // only initialize system if we're not in maintenance mode.
551
        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
552
            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
553
            $rewrite_rules = $this->loader->getShared(
554
                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
555
            );
556
            $rewrite_rules->flush();
557
            if ($verify_schema) {
558
                EEH_Activation::initialize_db_and_folders();
559
            }
560
            EEH_Activation::initialize_db_content();
561
            EEH_Activation::system_initialization();
562
            if ($initialize_addons_too) {
563
                $this->initialize_addons();
564
            }
565
        } else {
566
            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
567
        }
568
        if ($request_type === EE_System::req_type_new_activation
569
            || $request_type === EE_System::req_type_reactivation
570
            || (
571
                $request_type === EE_System::req_type_upgrade
572
                && $this->is_major_version_change()
573
            )
574
        ) {
575
            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
576
        }
577
    }
578
579
580
    /**
581
     * Initializes the db for all registered addons
582
     *
583
     * @throws EE_Error
584
     */
585
    public function initialize_addons()
586
    {
587
        // foreach registered addon, make sure its db is up-to-date too
588
        foreach ($this->registry->addons as $addon) {
589
            if ($addon instanceof EE_Addon) {
590
                $addon->initialize_db_if_no_migrations_required();
591
            }
592
        }
593
    }
594
595
596
    /**
597
     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
598
     *
599
     * @param    array  $version_history
600
     * @param    string $current_version_to_add version to be added to the version history
601
     * @return    boolean success as to whether or not this option was changed
602
     */
603
    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
604
    {
605
        if (! $version_history) {
606
            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
607
        }
608
        if ($current_version_to_add === null) {
609
            $current_version_to_add = espresso_version();
610
        }
611
        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
612
        // re-save
613
        return update_option('espresso_db_update', $version_history);
614
    }
615
616
617
    /**
618
     * Detects if the current version indicated in the has existed in the list of
619
     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
620
     *
621
     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
622
     *                                  If not supplied, fetches it from the options table.
623
     *                                  Also, caches its result so later parts of the code can also know whether
624
     *                                  there's been an update or not. This way we can add the current version to
625
     *                                  espresso_db_update, but still know if this is a new install or not
626
     * @return int one of the constants on EE_System::req_type_
627
     */
628
    public function detect_req_type($espresso_db_update = null)
629
    {
630
        if ($this->_req_type === null) {
631
            $espresso_db_update = ! empty($espresso_db_update)
632
                ? $espresso_db_update
633
                : $this->fix_espresso_db_upgrade_option();
634
            $this->_req_type = EE_System::detect_req_type_given_activation_history(
635
                $espresso_db_update,
636
                'ee_espresso_activation',
637
                espresso_version()
638
            );
639
            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
640
            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
641
        }
642
        return $this->_req_type;
643
    }
644
645
646
    /**
647
     * Returns whether or not there was a non-micro version change (ie, change in either
648
     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
649
     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
650
     *
651
     * @param $activation_history
652
     * @return bool
653
     */
654
    private function _detect_major_version_change($activation_history)
655
    {
656
        $previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
657
        $previous_version_parts = explode('.', $previous_version);
658
        $current_version_parts = explode('.', espresso_version());
659
        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
660
               && ($previous_version_parts[0] !== $current_version_parts[0]
661
                   || $previous_version_parts[1] !== $current_version_parts[1]
662
               );
663
    }
664
665
666
    /**
667
     * Returns true if either the major or minor version of EE changed during this request.
668
     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
669
     *
670
     * @return bool
671
     */
672
    public function is_major_version_change()
673
    {
674
        return $this->_major_version_change;
675
    }
676
677
678
    /**
679
     * Determines the request type for any ee addon, given three piece of info: the current array of activation
680
     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
681
     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
682
     * just activated to (for core that will always be espresso_version())
683
     *
684
     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
685
     *                                                 ee plugin. for core that's 'espresso_db_update'
686
     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
687
     *                                                 indicate that this plugin was just activated
688
     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
689
     *                                                 espresso_version())
690
     * @return int one of the constants on EE_System::req_type_*
691
     */
692
    public static function detect_req_type_given_activation_history(
693
        $activation_history_for_addon,
694
        $activation_indicator_option_name,
695
        $version_to_upgrade_to
696
    ) {
697
        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
698
        if ($activation_history_for_addon) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $activation_history_for_addon of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
699
            // it exists, so this isn't a completely new install
700
            // check if this version already in that list of previously installed versions
701
            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
702
                // it a version we haven't seen before
703
                if ($version_is_higher === 1) {
704
                    $req_type = EE_System::req_type_upgrade;
705
                } else {
706
                    $req_type = EE_System::req_type_downgrade;
707
                }
708
                delete_option($activation_indicator_option_name);
709
            } else {
710
                // its not an update. maybe a reactivation?
711
                if (get_option($activation_indicator_option_name, false)) {
712 View Code Duplication
                    if ($version_is_higher === -1) {
713
                        $req_type = EE_System::req_type_downgrade;
714
                    } elseif ($version_is_higher === 0) {
715
                        // we've seen this version before, but it's an activation. must be a reactivation
716
                        $req_type = EE_System::req_type_reactivation;
717
                    } else {// $version_is_higher === 1
718
                        $req_type = EE_System::req_type_upgrade;
719
                    }
720
                    delete_option($activation_indicator_option_name);
721 View Code Duplication
                } else {
722
                    // we've seen this version before and the activation indicate doesn't show it was just activated
723
                    if ($version_is_higher === -1) {
724
                        $req_type = EE_System::req_type_downgrade;
725
                    } elseif ($version_is_higher === 0) {
726
                        // we've seen this version before and it's not an activation. its normal request
727
                        $req_type = EE_System::req_type_normal;
728
                    } else {// $version_is_higher === 1
729
                        $req_type = EE_System::req_type_upgrade;
730
                    }
731
                }
732
            }
733
        } else {
734
            // brand new install
735
            $req_type = EE_System::req_type_new_activation;
736
            delete_option($activation_indicator_option_name);
737
        }
738
        return $req_type;
739
    }
740
741
742
    /**
743
     * Detects if the $version_to_upgrade_to is higher than the most recent version in
744
     * the $activation_history_for_addon
745
     *
746
     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
747
     *                                             sometimes containing 'unknown-date'
748
     * @param string $version_to_upgrade_to        (current version)
749
     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
750
     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
751
     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
752
     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
753
     */
754
    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
755
    {
756
        // find the most recently-activated version
757
        $most_recently_active_version =
758
            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
759
        return version_compare($version_to_upgrade_to, $most_recently_active_version);
760
    }
761
762
763
    /**
764
     * Gets the most recently active version listed in the activation history,
765
     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
766
     *
767
     * @param array $activation_history  (keys are versions, values are arrays of times activated,
768
     *                                   sometimes containing 'unknown-date'
769
     * @return string
770
     */
771
    private static function _get_most_recently_active_version_from_activation_history($activation_history)
772
    {
773
        $most_recently_active_version_activation = '1970-01-01 00:00:00';
774
        $most_recently_active_version = '0.0.0.dev.000';
775
        if (is_array($activation_history)) {
776
            foreach ($activation_history as $version => $times_activated) {
777
                // check there is a record of when this version was activated. Otherwise,
778
                // mark it as unknown
779
                if (! $times_activated) {
780
                    $times_activated = array('unknown-date');
781
                }
782
                if (is_string($times_activated)) {
783
                    $times_activated = array($times_activated);
784
                }
785
                foreach ($times_activated as $an_activation) {
786
                    if ($an_activation !== 'unknown-date'
787
                        && $an_activation
788
                           > $most_recently_active_version_activation) {
789
                        $most_recently_active_version = $version;
790
                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
791
                            ? '1970-01-01 00:00:00'
792
                            : $an_activation;
793
                    }
794
                }
795
            }
796
        }
797
        return $most_recently_active_version;
798
    }
799
800
801
    /**
802
     * This redirects to the about EE page after activation
803
     *
804
     * @return void
805
     */
806
    public function redirect_to_about_ee()
807
    {
808
        $notices = EE_Error::get_notices(false);
809
        // if current user is an admin and it's not an ajax or rest request
810
        if (! isset($notices['errors'])
811
            && $this->request->isAdmin()
812
            && apply_filters(
813
                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
814
                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
815
            )
816
        ) {
817
            $query_params = array('page' => 'espresso_about');
818
            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
819
                $query_params['new_activation'] = true;
820
            }
821
            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
822
                $query_params['reactivation'] = true;
823
            }
824
            $url = add_query_arg($query_params, admin_url('admin.php'));
825
            wp_safe_redirect($url);
826
            exit();
827
        }
828
    }
829
830
831
    /**
832
     * load_core_configuration
833
     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
834
     * which runs during the WP 'plugins_loaded' action at priority 5
835
     *
836
     * @return void
837
     * @throws ReflectionException
838
     */
839
    public function load_core_configuration()
840
    {
841
        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
842
        $this->loader->getShared('EE_Load_Textdomain');
843
        // load textdomain
844
        EE_Load_Textdomain::load_textdomain();
845
        // load and setup EE_Config and EE_Network_Config
846
        $config = $this->loader->getShared('EE_Config');
847
        $this->loader->getShared('EE_Network_Config');
848
        // setup autoloaders
849
        // enable logging?
850
        if ($config->admin->use_full_logging) {
851
            $this->loader->getShared('EE_Log');
852
        }
853
        // check for activation errors
854
        $activation_errors = get_option('ee_plugin_activation_errors', false);
855
        if ($activation_errors) {
856
            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
857
            update_option('ee_plugin_activation_errors', false);
858
        }
859
        // get model names
860
        $this->_parse_model_names();
861
        // load caf stuff a chance to play during the activation process too.
862
        $this->_maybe_brew_regular();
863
        // configure custom post type definitions
864
        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
865
        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
866
        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
867
    }
868
869
870
    /**
871
     * cycles through all of the models/*.model.php files, and assembles an array of model names
872
     *
873
     * @return void
874
     * @throws ReflectionException
875
     */
876
    private function _parse_model_names()
877
    {
878
        // get all the files in the EE_MODELS folder that end in .model.php
879
        $models = glob(EE_MODELS . '*.model.php');
880
        $model_names = array();
881
        $non_abstract_db_models = array();
882
        foreach ($models as $model) {
883
            // get model classname
884
            $classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
885
            $short_name = str_replace('EEM_', '', $classname);
886
            $reflectionClass = new ReflectionClass($classname);
887
            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
888
                $non_abstract_db_models[ $short_name ] = $classname;
889
            }
890
            $model_names[ $short_name ] = $classname;
891
        }
892
        $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
893
        $this->registry->non_abstract_db_models = apply_filters(
894
            'FHEE__EE_System__parse_implemented_model_names',
895
            $non_abstract_db_models
896
        );
897
    }
898
899
900
    /**
901
     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
902
     * that need to be setup before our EE_System launches.
903
     *
904
     * @return void
905
     * @throws DomainException
906
     * @throws InvalidArgumentException
907
     * @throws InvalidDataTypeException
908
     * @throws InvalidInterfaceException
909
     * @throws InvalidClassException
910
     * @throws InvalidFilePathException
911
     */
912
    private function _maybe_brew_regular()
913
    {
914
        /** @var Domain $domain */
915
        $domain = DomainFactory::getShared(
916
            new FullyQualifiedName(
917
                'EventEspresso\core\domain\Domain'
918
            ),
919
            array(
920
                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
921
                Version::fromString(espresso_version()),
922
            )
923
        );
924
        if ($domain->isCaffeinated()) {
925
            require_once EE_CAFF_PATH . 'brewing_regular.php';
926
        }
927
    }
928
929
930
    /**
931
     * register_shortcodes_modules_and_widgets
932
     * generate lists of shortcodes and modules, then verify paths and classes
933
     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
934
     * which runs during the WP 'plugins_loaded' action at priority 7
935
     *
936
     * @access public
937
     * @return void
938
     * @throws Exception
939
     */
940
    public function register_shortcodes_modules_and_widgets()
941
    {
942
        try {
943
            // load, register, and add shortcodes the new way
944
            if ($this->request->isFrontend() || $this->request->isIframe()) {
945
                $this->loader->getShared(
946
                    'EventEspresso\core\services\shortcodes\ShortcodesManager',
947
                    array(
948
                        // and the old way, but we'll put it under control of the new system
949
                        EE_Config::getLegacyShortcodesManager(),
950
                    )
951
                );
952
            }
953
        } catch (Exception $exception) {
954
            new ExceptionStackTraceDisplay($exception);
955
        }
956
        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
957
        // check for addons using old hook point
958
        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
959
            $this->_incompatible_addon_error();
960
        }
961
    }
962
963
964
    /**
965
     * _incompatible_addon_error
966
     *
967
     * @access public
968
     * @return void
969
     */
970
    private function _incompatible_addon_error()
971
    {
972
        // get array of classes hooking into here
973
        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
974
            'AHEE__EE_System__register_shortcodes_modules_and_addons'
975
        );
976
        if (! empty($class_names)) {
977
            $msg = __(
978
                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
979
                'event_espresso'
980
            );
981
            $msg .= '<ul>';
982
            foreach ($class_names as $class_name) {
983
                $msg .= '<li><b>Event Espresso - '
984
                        . str_replace(
985
                            array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
986
                            '',
987
                            $class_name
988
                        ) . '</b></li>';
989
            }
990
            $msg .= '</ul>';
991
            $msg .= __(
992
                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
993
                'event_espresso'
994
            );
995
            // save list of incompatible addons to wp-options for later use
996
            add_option('ee_incompatible_addons', $class_names, '', 'no');
997
            if (is_admin()) {
998
                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
999
            }
1000
        }
1001
    }
1002
1003
1004
    /**
1005
     * brew_espresso
1006
     * begins the process of setting hooks for initializing EE in the correct order
1007
     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1008
     * which runs during the WP 'plugins_loaded' action at priority 9
1009
     *
1010
     * @return void
1011
     */
1012
    public function brew_espresso()
1013
    {
1014
        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1015
        // load some final core systems
1016
        add_action('init', array($this, 'set_hooks_for_core'), 1);
1017
        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1018
        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1019
        add_action('init', array($this, 'load_controllers'), 7);
1020
        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1021
        add_action('init', array($this, 'initialize'), 10);
1022
        add_action('init', array($this, 'initialize_last'), 100);
1023
        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1024
            // pew pew pew
1025
            $this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1026
            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1027
        }
1028
        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1029
    }
1030
1031
1032
    /**
1033
     *    set_hooks_for_core
1034
     *
1035
     * @access public
1036
     * @return    void
1037
     * @throws EE_Error
1038
     */
1039
    public function set_hooks_for_core()
1040
    {
1041
        $this->_deactivate_incompatible_addons();
1042
        do_action('AHEE__EE_System__set_hooks_for_core');
1043
        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1044
        // caps need to be initialized on every request so that capability maps are set.
1045
        // @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1046
        $this->registry->CAP->init_caps();
1047
    }
1048
1049
1050
    /**
1051
     * Using the information gathered in EE_System::_incompatible_addon_error,
1052
     * deactivates any addons considered incompatible with the current version of EE
1053
     */
1054
    private function _deactivate_incompatible_addons()
1055
    {
1056
        $incompatible_addons = get_option('ee_incompatible_addons', array());
1057
        if (! empty($incompatible_addons)) {
1058
            $active_plugins = get_option('active_plugins', array());
1059
            foreach ($active_plugins as $active_plugin) {
1060
                foreach ($incompatible_addons as $incompatible_addon) {
1061
                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1062
                        unset($_GET['activate']);
1063
                        espresso_deactivate_plugin($active_plugin);
1064
                    }
1065
                }
1066
            }
1067
        }
1068
    }
1069
1070
1071
    /**
1072
     *    perform_activations_upgrades_and_migrations
1073
     *
1074
     * @access public
1075
     * @return    void
1076
     */
1077
    public function perform_activations_upgrades_and_migrations()
1078
    {
1079
        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1080
    }
1081
1082
1083
    /**
1084
     * @return void
1085
     * @throws DomainException
1086
     */
1087
    public function load_CPTs_and_session()
1088
    {
1089
        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1090
        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1091
        $register_custom_taxonomies = $this->loader->getShared(
1092
            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1093
        );
1094
        $register_custom_taxonomies->registerCustomTaxonomies();
1095
        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1096
        $register_custom_post_types = $this->loader->getShared(
1097
            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1098
        );
1099
        $register_custom_post_types->registerCustomPostTypes();
1100
        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1101
        $register_custom_taxonomy_terms = $this->loader->getShared(
1102
            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1103
        );
1104
        $register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1105
        // load legacy Custom Post Types and Taxonomies
1106
        $this->loader->getShared('EE_Register_CPTs');
1107
        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1108
    }
1109
1110
1111
    /**
1112
     * load_controllers
1113
     * this is the best place to load any additional controllers that needs access to EE core.
1114
     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1115
     * time
1116
     *
1117
     * @access public
1118
     * @return void
1119
     */
1120
    public function load_controllers()
1121
    {
1122
        do_action('AHEE__EE_System__load_controllers__start');
1123
        // let's get it started
1124
        if (! $this->maintenance_mode->level()
1125
            && ($this->request->isFrontend() || $this->request->isFrontAjax())
1126
        ) {
1127
            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1128
            $this->loader->getShared('EE_Front_Controller');
1129
        } elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1130
            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1131
            $this->loader->getShared('EE_Admin');
1132
        }
1133
        do_action('AHEE__EE_System__load_controllers__complete');
1134
    }
1135
1136
1137
    /**
1138
     * core_loaded_and_ready
1139
     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1140
     *
1141
     * @access public
1142
     * @return void
1143
     * @throws Exception
1144
     */
1145
    public function core_loaded_and_ready()
1146
    {
1147
        if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1148
            try {
1149
                $this->loader->getShared('EventEspresso\core\services\assets\Registry');
1150
                $this->loader->getShared('EventEspresso\core\domain\services\assets\CoreAssetManager');
1151
                if (function_exists('register_block_type')) {
1152
                    $this->loader->getShared(
1153
                        'EventEspresso\core\services\editor\BlockRegistrationManager'
1154
                    );
1155
                }
1156
            } catch (Exception $exception) {
1157
                new ExceptionStackTraceDisplay($exception);
1158
            }
1159
        }
1160
        if ($this->request->isAdmin()
1161
            || $this->request->isEeAjax()
1162
            || $this->request->isFrontend()
1163
        ) {
1164
            $this->loader->getShared('EE_Session');
1165
        }
1166
        do_action('AHEE__EE_System__core_loaded_and_ready');
1167
        // load_espresso_template_tags
1168
        if (is_readable(EE_PUBLIC . 'template_tags.php')
1169
            && ($this->request->isFrontend()
1170
                || $this->request->isAdmin()
1171
                || $this->request->isIframe()
1172
                || $this->request->isFeed()
1173
            )
1174
        ) {
1175
            require_once EE_PUBLIC . 'template_tags.php';
1176
        }
1177
        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1178
    }
1179
1180
1181
    /**
1182
     * initialize
1183
     * this is the best place to begin initializing client code
1184
     *
1185
     * @access public
1186
     * @return void
1187
     */
1188
    public function initialize()
1189
    {
1190
        do_action('AHEE__EE_System__initialize');
1191
    }
1192
1193
1194
    /**
1195
     * initialize_last
1196
     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1197
     * initialize has done so
1198
     *
1199
     * @access public
1200
     * @return void
1201
     */
1202
    public function initialize_last()
1203
    {
1204
        do_action('AHEE__EE_System__initialize_last');
1205
        /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1206
        $rewrite_rules = $this->loader->getShared(
1207
            'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1208
        );
1209
        $rewrite_rules->flushRewriteRules();
1210
        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1211
        if (($this->request->isAjax() || $this->request->isAdmin())
1212
            && $this->maintenance_mode->models_can_query()) {
1213
            $this->loader->getShared('EventEspresso\core\services\privacy\export\PersonalDataExporterManager');
1214
            $this->loader->getShared('EventEspresso\core\services\privacy\erasure\PersonalDataEraserManager');
1215
        }
1216
    }
1217
1218
1219
    /**
1220
     * @return void
1221
     * @throws EE_Error
1222
     */
1223
    public function addEspressoToolbar()
1224
    {
1225
        $this->loader->getShared(
1226
            'EventEspresso\core\domain\services\admin\AdminToolBar',
1227
            array($this->registry->CAP)
1228
        );
1229
    }
1230
1231
1232
    /**
1233
     * do_not_cache
1234
     * sets no cache headers and defines no cache constants for WP plugins
1235
     *
1236
     * @access public
1237
     * @return void
1238
     */
1239
    public static function do_not_cache()
1240
    {
1241
        // set no cache constants
1242
        if (! defined('DONOTCACHEPAGE')) {
1243
            define('DONOTCACHEPAGE', true);
1244
        }
1245
        if (! defined('DONOTCACHCEOBJECT')) {
1246
            define('DONOTCACHCEOBJECT', true);
1247
        }
1248
        if (! defined('DONOTCACHEDB')) {
1249
            define('DONOTCACHEDB', true);
1250
        }
1251
        // add no cache headers
1252
        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1253
        // plus a little extra for nginx and Google Chrome
1254
        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1255
        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1256
        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1257
    }
1258
1259
1260
    /**
1261
     *    extra_nocache_headers
1262
     *
1263
     * @access    public
1264
     * @param $headers
1265
     * @return    array
1266
     */
1267
    public static function extra_nocache_headers($headers)
1268
    {
1269
        // for NGINX
1270
        $headers['X-Accel-Expires'] = 0;
1271
        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1272
        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1273
        return $headers;
1274
    }
1275
1276
1277
    /**
1278
     *    nocache_headers
1279
     *
1280
     * @access    public
1281
     * @return    void
1282
     */
1283
    public static function nocache_headers()
1284
    {
1285
        nocache_headers();
1286
    }
1287
1288
1289
    /**
1290
     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1291
     * never returned with the function.
1292
     *
1293
     * @param  array $exclude_array any existing pages being excluded are in this array.
1294
     * @return array
1295
     */
1296
    public function remove_pages_from_wp_list_pages($exclude_array)
1297
    {
1298
        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1299
    }
1300
}
1301