1
|
|
|
<?php |
2
|
|
|
/* HEADER */ // phpcs:ignore |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* This class handles management of the actual PHP autoloader. |
6
|
|
|
*/ |
7
|
|
|
class Autoloader { |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Checks to see whether or not the autoloader should be initialized and then initializes it if so. |
11
|
|
|
* |
12
|
|
|
* @param Container|null $container The container we want to use for autoloader initialization. If none is given |
13
|
|
|
* then a container will be created automatically. |
14
|
|
|
*/ |
15
|
|
|
public static function init( $container = null ) { |
16
|
|
|
// The container holds and manages the lifecycle of our dependencies |
17
|
|
|
// to make them easier to work with and increase flexibility. |
18
|
|
|
if ( ! isset( $container ) ) { |
19
|
|
|
require_once __DIR__ . '/class-container.php'; |
20
|
|
|
$container = new Container(); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
// phpcs:disable Generic.Commenting.DocComment.MissingShort |
24
|
|
|
|
25
|
|
|
/** @var Autoloader_Handler $autoloader_handler */ |
26
|
|
|
$autoloader_handler = $container->get( Autoloader_Handler::class ); |
27
|
|
|
|
28
|
|
|
// If the autoloader is already initializing it means that it has included us as the latest. |
29
|
|
|
$was_included_by_autoloader = $autoloader_handler->is_initializing(); |
30
|
|
|
|
31
|
|
|
/** @var Plugin_Locator $plugin_locator */ |
32
|
|
|
$plugin_locator = $container->get( Plugin_Locator::class ); |
33
|
|
|
|
34
|
|
|
/** @var Plugins_Handler $plugins_handler */ |
35
|
|
|
$plugins_handler = $container->get( Plugins_Handler::class ); |
36
|
|
|
|
37
|
|
|
// The current plugin is the one that we are attempting to initialize here. |
38
|
|
|
$current_plugin = $plugin_locator->find_current_plugin(); |
39
|
|
|
|
40
|
|
|
// The active plugins are those that we were able to discover on the site. This list will not |
41
|
|
|
// include mu-plugins, those activated by code, or those who are hidden by filtering. We also |
42
|
|
|
// want to take care to not consider the current plugin unknown if it was included by an |
43
|
|
|
// autoloader. This avoids the case where a plugin will be marked "active" while deactivated |
44
|
|
|
// due to it having the latest autoloader. |
45
|
|
|
$active_plugins = $plugins_handler->get_active_plugins( true, ! $was_included_by_autoloader ); |
46
|
|
|
|
47
|
|
|
// The cached plugins are all of those that were active or discovered by the autoloader during a previous request. |
48
|
|
|
// Note that it's possible this list will include plugins that have since been deactivated, but after a request |
49
|
|
|
// the cache should be updated and the deactivated plugins will be removed. |
50
|
|
|
$cached_plugins = $plugins_handler->get_cached_plugins(); |
51
|
|
|
|
52
|
|
|
// We combine the active list and cached list to preemptively load classes for plugins that are |
53
|
|
|
// presently unknown but will be loaded during the request. While this may result in us considering packages in |
54
|
|
|
// deactivated plugins there shouldn't be any problems as a result and the eventual consistency is sufficient. |
55
|
|
|
$all_plugins = array_merge( $active_plugins, $cached_plugins ); |
56
|
|
|
|
57
|
|
|
// In particular we also include the current plugin to address the case where it is the latest autoloader |
58
|
|
|
// but also unknown (and not cached). We don't want it in the active list because we don't know that it |
59
|
|
|
// is active but we need it in the all plugins list so that it is considered by the autoloader. |
60
|
|
|
$all_plugins[] = $current_plugin; |
61
|
|
|
|
62
|
|
|
// We require uniqueness in the array to avoid processing the same plugin more than once. |
63
|
|
|
$all_plugins = array_values( array_unique( $all_plugins ) ); |
64
|
|
|
|
65
|
|
|
/** @var Latest_Autoloader_Guard $guard */ |
66
|
|
|
$guard = $container->get( Latest_Autoloader_Guard::class ); |
67
|
|
|
if ( $guard->should_stop_init( $current_plugin, $all_plugins, $was_included_by_autoloader ) ) { |
68
|
|
|
return; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
// Initialize the autoloader using the handler now that we're ready. |
72
|
|
|
$autoloader_handler->activate_autoloader( $all_plugins ); |
73
|
|
|
|
74
|
|
|
/** @var Hook_Manager $hook_manager */ |
75
|
|
|
$hook_manager = $container->get( Hook_Manager::class ); |
76
|
|
|
|
77
|
|
|
// When the active and cached plugin lists do not match we should |
78
|
|
|
// update the cache. This will prevent plugins that have been |
79
|
|
|
// deactivated from being considered in other requests. |
80
|
|
|
$hook_manager->add_action( |
81
|
|
|
'shutdown', |
82
|
|
|
function () use ( $plugins_handler, $cached_plugins, $was_included_by_autoloader ) { |
83
|
|
|
// Don't save a broken cache if an error happens during some plugin's initialization. |
84
|
|
|
if ( ! did_action( 'plugins_loaded' ) ) { |
85
|
|
|
// Ensure that the cache is emptied to prevent consecutive failures if the cache is to blame. |
86
|
|
|
if ( ! empty( $cached_plugins ) ) { |
87
|
|
|
$plugins_handler->cache_plugins( array() ); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
return; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
// Load the active plugins fresh since the list we pulled earlier might not contain |
94
|
|
|
// plugins that were activated but did not reset the autoloader. This happens |
95
|
|
|
// when a plugin is in the cache but not "active" when the autoloader loads. |
96
|
|
|
// We also want to make sure that plugins which are deactivating are not |
97
|
|
|
// considered "active" so that they will be removed from the cache now. |
98
|
|
|
$active_plugins = $plugins_handler->get_active_plugins( false, ! $was_included_by_autoloader ); |
99
|
|
|
|
100
|
|
|
// The paths should be sorted for easy comparisons with those loaded from the cache. |
101
|
|
|
// Note we don't need to sort the cached entries because they're already sorted. |
102
|
|
|
sort( $active_plugins ); |
103
|
|
|
|
104
|
|
|
// We don't want to waste time saving a cache that hasn't changed. |
105
|
|
|
if ( $cached_plugins === $active_plugins ) { |
106
|
|
|
return; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$plugins_handler->cache_plugins( $active_plugins ); |
110
|
|
|
} |
111
|
|
|
); |
112
|
|
|
|
113
|
|
|
// phpcs:enable Generic.Commenting.DocComment.MissingShort |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
|