PluginProbe
Solid Performance – Your No-Code Caching, Performance, & Page Speed Solution / trunk
Solid Performance – Your No-Code Caching, Performance, & Page Speed Solution vtrunk
2.0.1 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.9.0 2.0.0
solid-performance / src / Performance / Core.php

Core.php in Solid Performance – Your No-Code Caching, Performance, & Page Speed Solution trunk, at src/Performance/Core.php

281 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The main plugin class.
4 *
5 * @since 0.1.0
6 *
7 * @package SolidWP\Performance
8 */
9
10 declare( strict_types=1 );
11
12 namespace SolidWP\Performance;
13
14 use InvalidArgumentException;
15 use RuntimeException;
16 use SolidWP\Performance\Contracts\Service_Provider;
17 use SolidWP\Performance\Page_Cache\Cache_Path;
18 use SolidWP\Performance\Psr\Container\ContainerInterface;
19 use SolidWP\Performance\StellarWP\ContainerContract\ContainerInterface as StellarContainerInterface;
20
21 if ( ! defined( 'ABSPATH' ) ) {
22 exit;
23 }
24
25 /**
26 * The primary class responsible for booting up the plugin.
27 *
28 * @since 0.1.0
29 *
30 * @package SolidWP\Performance
31 */
32 final class Core {
33
34 public const PLUGIN_FILE = 'solid_performance.plugin_file';
35 public const PLUGIN_DIR = 'solid_performance.plugin_dir';
36 public const PLUGIN_URL = 'solid_performance.plugin_url';
37 public const PLUGIN_BASENAME = 'solid_performance.plugin_basename';
38 public const PLUGIN_VERSION = 'solid_performance.plugin_version';
39 public const CACHE_DIR = 'solid_performance.cache_dir';
40 public const ADVANCED_CACHE_PATH = 'solid_performance.advanced_cache_path';
41
42 /**
43 * The server path to the plugin's main file.
44 *
45 * @var string
46 */
47 private string $plugin_file;
48
49 /**
50 * The centralized container.
51 *
52 * @since 0.1.0
53 *
54 * @var Container
55 */
56 private Container $container;
57
58 /**
59 * An array of providers to register within the container before
60 * WordPress is fully bootstrapped, e.g. in advanced-cache.php.
61 *
62 * @var array<int, class-string<Service_Provider>>
63 */
64 private array $early_providers = [
65 Log\Provider::class,
66 Memoize\Provider::class,
67 Config\Provider::class,
68 View\Provider::class,
69 Cache_Delivery\Provider::class,
70 Page_Cache\Request_Context\Provider::class,
71 Page_Cache\Meta\Provider::class,
72 Page_Cache\Provider::class,
73
74 // This should always be last, to ensure dependencies have been built.
75 Update\Provider::class,
76 ];
77
78 /**
79 * An array of providers to register within the container after
80 * WordPress is fully bootstrapped.
81 *
82 * @since 0.1.0
83 *
84 * @var array<int, class-string<Service_Provider>>
85 */
86 private array $providers = [
87 Database\Provider::class,
88 Storage\Provider::class,
89 Lock\Provider::class,
90 Assets\Provider::class,
91 Page_Cache\Purge\Provider::class,
92 Preload\Provider::class,
93 Admin\Provider::class,
94 API\Provider::class,
95 Notices\Provider::class,
96 Pipelines\Provider::class,
97 Telemetry\Provider::class,
98 Image_Transformation\Provider::class,
99 WP_CLI\Provider::class,
100 Shutdown\Provider::class,
101 Dom\Provider::class,
102 Cron\Provider::class,
103 ];
104
105 /**
106 * The singleton instance for the plugin.
107 *
108 * @var Core
109 */
110 private static self $instance;
111
112 /**
113 * @param string $plugin_file The full server path to the main plugin file.
114 * @param Container $container The container instance.
115 */
116 private function __construct(
117 string $plugin_file,
118 Container $container
119 ) {
120 $this->plugin_file = $plugin_file;
121 $this->container = $container;
122 $this->container->singleton( ContainerInterface::class, $this->container );
123 $this->container->singleton( StellarContainerInterface::class, $this->container );
124
125 // Set container variables available to pre bootstrap providers.
126 $this->container->setVar( self::PLUGIN_FILE, $this->plugin_file );
127 $this->container->setVar( self::PLUGIN_VERSION, $this->get_plugin_version() );
128 $this->container->setVar( self::CACHE_DIR, WP_CONTENT_DIR . '/cache/solid-performance' );
129 $this->container->setVar( self::ADVANCED_CACHE_PATH, WP_CONTENT_DIR . '/advanced-cache.php' );
130
131 // Set the cache dir early so all providers can use it.
132 $this->register_mandatory_definitions();
133
134 // Register pre bootstrap providers early.
135 $this->register_early_providers();
136 }
137
138 /**
139 * Get the singleton instance of our plugin.
140 *
141 * @param string|null $plugin_file The full server path to the main plugin file.
142 * @param Container|null $container The container instance.
143 *
144 * @throws InvalidArgumentException If no existing instance and no plugin file or container is provided.
145 *
146 * @return Core
147 */
148 public static function instance( ?string $plugin_file = null, ?Container $container = null ): Core {
149 if ( ! isset( self::$instance ) ) {
150 if ( ! $plugin_file ) {
151 throw new InvalidArgumentException( 'You must provide a $plugin_file path' );
152 }
153
154 if ( ! $container ) {
155 throw new InvalidArgumentException( sprintf( 'You must provide a %s instance!', Container::class ) );
156 }
157
158 self::$instance = new self( $plugin_file, $container );
159 }
160
161 return self::$instance;
162 }
163
164 /**
165 * Reload service provider container definitions.
166 *
167 * @return Core
168 */
169 public function reload(): Core {
170 $this->register_mandatory_definitions();
171 $this->register_early_providers();
172
173 return $this->init();
174 }
175
176 /**
177 * Initialize the plugin.
178 *
179 * @action plugins_loaded
180 *
181 * @return Core
182 */
183 public function init(): Core {
184 $this->register_mandatory_definitions();
185
186 // Set remaining container variables now that WordPress is fully bootstrapped.
187 $this->container->setVar( self::PLUGIN_DIR, plugin_dir_path( $this->plugin_file ) );
188 $this->container->setVar( self::PLUGIN_URL, plugin_dir_url( $this->plugin_file ) );
189 $this->container->setVar( self::PLUGIN_BASENAME, plugin_basename( $this->plugin_file ) );
190
191 // Register remaining providers now that WP is fully bootstrapped.
192 foreach ( $this->providers as $class ) {
193 $this->container->get( $class )->register( $this->container );
194 }
195
196 return self::$instance;
197 }
198
199 /**
200 * Returns the container instance.
201 *
202 * @return Container
203 */
204 public function container(): Container {
205 return $this->container;
206 }
207
208 /**
209 * Prevent wakeup.
210 *
211 * @throws RuntimeException When attempting to wake up this instance.
212 */
213 public function __wakeup(): void {
214 throw new RuntimeException( 'method not implemented' );
215 }
216
217 /**
218 * Prevent sleep.
219 *
220 * @throws RuntimeException When attempting to sleep this instance.
221 */
222 public function __sleep(): array {
223 throw new RuntimeException( 'method not implemented' );
224 }
225
226 /**
227 * Prevent cloning.
228 *
229 * @throws RuntimeException When attempting to clone this instance.
230 */
231 private function __clone() {
232 throw new RuntimeException( 'Cloning not allowed' );
233 }
234
235 /**
236 * Mandatory container definitions that run both early and on init.
237 *
238 * @return void
239 */
240 private function register_mandatory_definitions(): void {
241 $this->container->when( Cache_Path::class )
242 ->needs( '$cache_dir' )
243 ->give( static fn ( $c ) => $c->get( self::CACHE_DIR ) );
244 }
245
246 /**
247 * Register early loaded bootstrap providers.
248 *
249 * @return void
250 */
251 private function register_early_providers(): void {
252 foreach ( $this->early_providers as $provider ) {
253 $this->container->get( $provider )->register( $this->container );
254 }
255 }
256
257 /**
258 * Get the plugin's current version.
259 *
260 * @throws RuntimeException If we are unable to retrieve the plugin version.
261 *
262 * @return string
263 */
264 private function get_plugin_version(): string {
265 $content = file_get_contents( $this->plugin_file, false, null, 0, 8 * KB_IN_BYTES );
266
267 // Prevent race condition if the solid-performance file is already deleted.
268 if ( ! $content ) {
269 return '0.0.0';
270 }
271
272 $pattern = '/^ \* Version:\s*(.+)$/m';
273
274 if ( preg_match( $pattern, $content, $matches ) ) {
275 return trim( $matches[1] );
276 }
277
278 throw new RuntimeException( sprintf( 'Unable to read plugin version from "%s"', $this->plugin_file ) );
279 }
280 }
281