PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.16.0
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.16.0
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / classes / WordPress / NitroPack.php
nitropack / classes / WordPress Last commit date
Config.php 2 years ago NitroPack.php 2 years ago Notifications.php 3 years ago
NitroPack.php
495 lines
1 <?php
2 namespace NitroPack\WordPress;
3
4 use \NitroPack\SDK\Filesystem;
5
6 class NitroPack {
7 private static $instance = NULL;
8 public static $nitroDirMigrated = false;
9 public static $nitroConfigMigrated = false;
10 public static $preUpdatePosts = array();
11 public static $preUpdateTaxonomies = array();
12 public static $preUpdateMeta = array();
13 public static $ignoreUpdatePostIDs = array();
14 public static $np_loggedWarmups = array();
15 public static $optionsToCache = [
16 'cache_handler_cache_handler',
17 'woocommerce_default_customer_address',
18 [ "wc_aelia_currency_switcher" => "ipgeolocation_enabled"]
19 ];
20
21 public static function getInstance() {
22 if (!self::$instance) {
23 self::$instance = new NitroPack();
24 }
25
26 return self::$instance;
27 }
28
29 public static function getDataDir() {
30 $isRaidBoxes = \NitroPack\Integration\Hosting\Raidboxes::detect();
31 $isPantheon = \NitroPack\Integration\Hosting\Pantheon::detect();
32 $isWpe = \NitroPack\Integration\Hosting\WPEngine::detect();
33 $isCloudways = \NitroPack\Integration\Hosting\Cloudways::detect();
34 $isRocketNet = \NitroPack\Integration\Hosting\RocketNet::detect();
35 $currentFilePath = __FILE__;
36 $wpContentDir = WP_CONTENT_DIR;
37
38 if ($isWpe) {
39 $currentFilePath = preg_replace("@^/sites/@", "/nas/content/live/", $currentFilePath);
40 $wpContentDir = preg_replace("@^/sites/@", "/nas/content/live/", $wpContentDir);
41 }
42
43 $oldNitroDirs = [
44 nitropack_trailingslashit($wpContentDir) . 'nitropack',
45 nitropack_trailingslashit($wpContentDir) . 'cache/' . substr(md5($currentFilePath), 0, 7) . "-nitropack",
46 ];
47 $newNitroDir = nitropack_trailingslashit($wpContentDir) . 'cache/' . NITROPACK_CACHE_DIR_NAME;
48 $nitroDir = $newNitroDir;
49
50 if ($isRaidBoxes || $isRocketNet || $isCloudways) {
51 $nitroDir = $oldNitroDirs[0];
52 } else if ($isPantheon) {
53 $nitroDir = nitropack_trailingslashit($wpContentDir) . 'uploads/' . NITROPACK_CACHE_DIR_NAME;
54 }
55
56 $possibleDirs = array_unique(array_merge($oldNitroDirs, [$newNitroDir]));
57 $existingDirs = [];
58
59 foreach ($possibleDirs as $possibleDir) {
60 if (Filesystem::fileExists($possibleDir)) {
61 $existingDirs[] = $possibleDir;
62 }
63 }
64
65 if (count($existingDirs) == 1) {
66 $existingDir = array_shift($existingDirs);
67 if (is_link($existingDir)) {
68 $existingDir = readlink($existingDir);
69 }
70
71 if ($existingDir != $nitroDir) {
72 if (!Filesystem::fileExists($nitroDir) && !NITROPACK_USE_REDIS) {
73 // Existing installation, move to the new location
74
75 if (Filesystem::createDir(dirname($nitroDir)) && Filesystem::rename($existingDir, $nitroDir)) {
76 self::$nitroDirMigrated = true;
77 } else {
78 define('NITROPACK_DATA_DIR_WARNING', 'Unable to initialize cache dir because the PHP user does not have permission to create/rename directories under wp-content/. Running in legacy mode. Please contact support for help.');
79 $nitroDir = $existingDir;
80 }
81 }
82 }
83 }
84
85 return $nitroDir;
86 }
87
88 public static function getPluginDataDir() {
89 $isPantheon = \NitroPack\Integration\Hosting\Pantheon::detect();
90 $isWpe = \NitroPack\Integration\Hosting\WPEngine::detect();
91 $nitroDir = nitropack_trailingslashit(WP_CONTENT_DIR) . 'config-' . NITROPACK_CACHE_DIR_NAME;
92 $expectedNitroDir = $nitroDir;
93
94 if ($isWpe) {
95 $nitroDir = preg_replace("@^/sites/@", "/nas/content/live/", $nitroDir);
96 $expectedNitroDir = $nitroDir;
97 }
98
99 if ($isPantheon) {
100 $nitroDir = nitropack_trailingslashit(WP_CONTENT_DIR) . 'uploads/config-' . NITROPACK_CACHE_DIR_NAME;
101 $expectedNitroDir = $nitroDir;
102 }
103
104 $oldConfigFile = nitropack_trailingslashit(NITROPACK_DATA_DIR) . 'config.json';
105 $newConfigFile = nitropack_trailingslashit($nitroDir) . 'config.json';
106
107 if ($isWpe) {
108 // For WPE it works better if we keep the config file in the cache dir
109 $tmpConfigFile = $newConfigFile;
110 $newConfigFile = $oldConfigFile;
111 $oldConfigFile = $tmpConfigFile;
112
113 if (!Filesystem::fileExists($oldConfigFile) && Filesystem::fileExists(preg_replace("@^/nas/content/live/@", "/sites/", $oldConfigFile))) {
114 $oldConfigFile = preg_replace("@^/nas/content/live/@", "/sites/", $oldConfigFile);
115 }
116
117 $nitroDir = NITROPACK_DATA_DIR;
118 }
119
120 if (Filesystem::fileExists($oldConfigFile) && !Filesystem::fileExists($newConfigFile)) {
121 // Existing installation, move config to the new location
122
123 if (Filesystem::createDir($nitroDir) && Filesystem::rename($oldConfigFile, $newConfigFile)) {
124 self::$nitroConfigMigrated = true;
125 $oldHtaccessFile = nitropack_trailingslashit(NITROPACK_DATA_DIR) . '.htaccess';
126 $newHtaccessFile = nitropack_trailingslashit($nitroDir) . '.htaccess';
127 if (Filesystem::fileExists($oldHtaccessFile) && !Filesystem::fileExists($newHtaccessFile)) {
128 Filesystem::filePutContents($newHtaccessFile, Filesystem::fileGetContents($oldHtaccessFile));
129 }
130
131 if ($isWpe) {
132 Filesystem::deleteDir($expectedNitroDir);
133 }
134 } else {
135 define('NITROPACK_PLUGIN_DATA_DIR_WARNING', 'Unable to initialize plugin data dir because the PHP user does not have permission to create/rename directories under wp-content/. Running in legacy mode. Please contact support for help.');
136 $nitroDir = $isWpe ? $expectedNitroDir : NITROPACK_DATA_DIR;
137 }
138 }
139
140 return $nitroDir;
141 }
142
143 public static function isWpCli() {
144 return defined("WP_CLI") && WP_CLI;
145 }
146
147 private $sdkObjects;
148 private $disabledReason;
149 private $pageType;
150
151 public $Config;
152 public $Notifications;
153
154 public function __construct() {
155 $this->Config = new Config($this);
156 $this->Notifications = new Notifications($this);
157 $this->sdkObjects = array();
158 $this->disabledReason = NULL;
159 $this->pageType = NULL;
160 }
161
162 public function getDistribution() {
163 $dist = "regular";
164 $dbDist = NULL;
165
166 try {
167 if (function_exists("get_option")) {
168 $dbDist = get_option("nitropack-distribution", NULL);
169 }
170
171 if ($this->isConnected()) {
172 $sdk = $this->getSdk();
173 if (!$sdk) return $dbDist ? $dbDist : $dist;
174
175 $config = $sdk->getConfig();
176 if ($config) {
177 $dist = $config->Distribution;
178 }
179 } else if ($dbDist !== NULL) {
180 $dist = $dbDist;
181 }
182
183 if ($dbDist != $dist && function_exists("update_option")) {
184 update_option("nitropack-distribution", $dist);
185 }
186
187 return $dist;
188 } catch (Exception $e) {
189 return $dist;
190 }
191 }
192
193 public function getSiteConfig() {
194 $siteConfig = null;
195 $npConfig = $this->Config->get();
196 $currentUrl = $this -> getCurrentUrl();
197
198 $matchLength = 0;
199
200 foreach ($npConfig as $siteUrl => $config) {
201 if (stripos($siteUrl, "www.") === 0) {
202 $siteUrl = substr($siteUrl, 4);
203 }
204
205 if (stripos($currentUrl, $siteUrl) === 0 && strlen($siteUrl) > $matchLength) {
206 $siteConfig = $config;
207 $matchLength = strlen($siteUrl);
208 }
209 }
210
211 if (!$siteConfig) {
212 $matchLength = 0;
213 foreach ($npConfig as $siteUrl => $config) {
214 if (isset($config['additional_domains'])) {
215 foreach ($config['additional_domains'] as $additionalDomain) {
216 if (stripos($additionalDomain, "www.") === 0) {
217 $additionalDomain = substr($additionalDomain, 4);
218 }
219
220 if (stripos($currentUrl, $additionalDomain) === 0 && strlen($additionalDomain) > $matchLength) {
221 $siteConfig = $config;
222 $matchLength = strlen($additionalDomain);
223 }
224 }
225 }
226 }
227 }
228
229 return $siteConfig;
230 }
231
232 public function getSiteId() {
233 $siteConfig = $this->getSiteConfig();
234 return $siteConfig ? $siteConfig["siteId"] : NULL;
235 }
236
237 public function getSiteSecret() {
238 $siteConfig = $this->getSiteConfig();
239 return $siteConfig ? $siteConfig["siteSecret"] : NULL;
240 }
241
242 /**
243 * Bear in mind that get_home_url() is not defined in the context of advanced_cache.php
244 * so this will throw a fatal error if you call it at that point!
245 */
246 public static function getConfigKey() {
247 return preg_replace("/^https?:\/\/(.*)/", "$1", get_home_url());
248 }
249
250 public function getAdditionalDomains($siteId, $siteSecret) {
251 if (null !== $nitro = $this->getSdk($siteId, $siteSecret)) {
252 $config = $nitro->getConfig();
253 if (!property_exists($config->AdditionalDomains, 'Domains')) {
254 $nitro->fetchConfig();
255 }
256 return $config->AdditionalDomains->Domains;
257 }
258
259 return [];
260 }
261
262 public function isConnected() {
263 return !empty($this->getSiteId()) && !empty($this->getSiteSecret());
264 }
265
266 public function updateCurrentBlogConfig($siteId, $siteSecret, $blogId, $enableCompression = null) {
267 if ($enableCompression === null) {
268 $enableCompression = (get_option('nitropack-enableCompression') == 1);
269 }
270
271 $webhookToken = get_option('nitropack-webhookToken');
272 $hosting = nitropack_detect_hosting();
273
274 $home_url = get_home_url();
275 $admin_url = admin_url();
276 $alwaysBuffer = defined("NITROPACK_ALWAYS_BUFFER") ? NITROPACK_ALWAYS_BUFFER : true;
277 $configKey = self::getConfigKey();
278 $staticConfig = $this->Config->get();
279 $staticConfig[$configKey] = array(
280 "siteId" => $siteId,
281 "siteSecret" => $siteSecret,
282 "blogId" => $blogId,
283 "compression" => $enableCompression,
284 "webhookToken" => $webhookToken,
285 "home_url" => $home_url,
286 "admin_url" => $admin_url,
287 "hosting" => $hosting,
288 "alwaysBuffer" => $alwaysBuffer,
289 "isEzoicActive" => \NitroPack\Integration\Plugin\Ezoic::isActive(),
290 "isApoActive" => \NitroPack\Integration\Plugin\Cloudflare::isApoActive(),
291 "isNginxHelperActive" => \NitroPack\Integration\Plugin\NginxHelper::isActive(),
292 "isLateIntegrationInitRequired" => nitropack_is_late_integration_init_required(),
293 "isDlmActive" => \NitroPack\Integration\Plugin\DownloadManager::isActive(),
294 "isWoocommerceCacheHandlerActive" => \NitroPack\Integration\Plugin\WoocommerceCacheHandler::isActive(),
295 "isWoocommerceActive" => \NitroPack\Integration\Plugin\Woocommerce::isActive(),
296 "isAeliaCurrencySwitcherActive" => \NitroPack\Integration\Plugin\AeliaCurrencySwitcher::isActive(),
297 "isGeoTargetingWPActive" => \NitroPack\Integration\Plugin\GeoTargetingWP::isActive(),
298 "dlm_downloading_url" => \NitroPack\Integration\Plugin\DownloadManager::isActive() ? \NitroPack\Integration\Plugin\DownloadManager::downloadingUrl() : NULL,
299 "dlm_download_endpoint" => \NitroPack\Integration\Plugin\DownloadManager::isActive() ? \NitroPack\Integration\Plugin\DownloadManager::downloadEndpoint() : NULL,
300 "pluginVersion" => NITROPACK_VERSION,
301 "options_cache" => [],
302 "additional_domains" => $this->getAdditionalDomains($siteId, $siteSecret),
303 );
304 foreach (self::$optionsToCache as $opt) {
305 if (is_array($opt)) {
306 foreach($opt as $option => $suboption) {
307 if (empty($staticConfig[$configKey]["options_cache"][$option])) {
308 $staticConfig[$configKey]["options_cache"][$option] = [];
309 }
310 $optionValue = get_option($option);
311 if (!empty($optionValue)) {
312 $staticConfig[$configKey]["options_cache"][$option][$suboption] = $optionValue[$suboption];
313 } else {
314 $staticConfig[$configKey]["options_cache"][$option][$suboption] = null;
315 }
316 }
317 } else {
318 $staticConfig[$configKey]["options_cache"][$opt] = get_option($opt);
319 }
320 }
321 $configSetResult = $this->Config->set($staticConfig);
322
323 if (\NitroPack\Integration\Plugin\AeliaCurrencySwitcher::isActive()) {
324 try {
325 \NitroPack\Integration\Plugin\AeliaCurrencySwitcher::configureVariationCookies();
326 } catch (\Exception $e) {
327 // TODO: Log this error
328 }
329 }
330 if (\NitroPack\Integration\Plugin\GeoTargetingWP::isActive()) {
331 try {
332 \NitroPack\Integration\Plugin\GeoTargetingWP::configureVariationCookies();
333 } catch (\Exception $e) {
334 // TODO: Log this error
335 }
336 }
337
338 return $configSetResult;
339 }
340
341 public function unsetCurrentBlogConfig() {
342 $configKey = self::getConfigKey();
343 $staticConfig = $this->Config->get();
344 if (!empty($staticConfig[$configKey])) {
345 unset($staticConfig[$configKey]);
346 return $this->Config->set($staticConfig);
347 }
348
349 return true;
350 }
351
352 public function resetSdkInstances() {
353 $this->sdkObjects = [];
354 }
355
356 public function getSdk($siteId = null, $siteSecret = null, $urlOverride = NULL, $forwardExceptions = false) {
357 $siteConfig = $this->getSiteConfig();
358
359 $siteId = $siteId ?: (!empty($siteConfig) ? $siteConfig['siteId'] : NULL);
360 $siteSecret = $siteSecret ?: (!empty($siteConfig) ? $siteConfig['siteSecret'] : NULL);
361
362 if ($siteId && $siteSecret) {
363 try {
364 $userAgent = NULL; // It will be automatically detected by the SDK
365 $dataDir = nitropack_trailingslashit(NITROPACK_DATA_DIR) . $siteId; // dir without a trailing slash, because this is how the SDK expects it
366 $cacheKey = "{$siteId}:{$siteSecret}:{$dataDir}";
367
368 if ($urlOverride) {
369 $cacheKey .= ":{$urlOverride}";
370 }
371
372 if (!empty($this->sdkObjects[$cacheKey])) {
373 $nitro = $this->sdkObjects[$cacheKey];
374 } else {
375 if (!defined("NP_COOKIE_FILTER")) {
376 \NitroPack\SDK\NitroPack::addCookieFilter("nitropack_filter_non_original_cookies");
377 define("NP_COOKIE_FILTER", true);
378 do_action('np_set_cookie_filter');
379 }
380 if (!defined("NP_STORAGE_CONFIGURED")) {
381 if (defined("NITROPACK_USE_REDIS") && NITROPACK_USE_REDIS) {
382 \NitroPack\SDK\Filesystem::setStorageDriver(new \NitroPack\SDK\StorageDriver\Redis(
383 NITROPACK_REDIS_HOST,
384 NITROPACK_REDIS_PORT,
385 NITROPACK_REDIS_PASS,
386 NITROPACK_REDIS_DB
387 ));
388 }
389 define("NP_STORAGE_CONFIGURED", true);
390 }
391
392 if (!defined('NP_GEOLOCATION_PREFIX_DEFINED')) {
393 do_action('set_nitropack_geo_cache_prefix');
394 define('NP_GEOLOCATION_PREFIX_DEFINED', true);
395 }
396
397 if (defined("NITROPACK_CUSTOM_CACHE_PREFIX") && !defined('NP_CUSTOM_CACHE_PREFIX_SET')) {
398 \NitroPack\SDK\NitroPack::addCustomCachePrefix(NITROPACK_CUSTOM_CACHE_PREFIX);
399 define('NP_CUSTOM_CACHE_PREFIX_SET', true);
400 }
401
402 $nitro = new \NitroPack\SDK\NitroPack($siteId, $siteSecret, $userAgent, $urlOverride, $dataDir);
403 $this->sdkObjects[$cacheKey] = $nitro;
404 }
405 } catch (\Exception $e) {
406 if ($forwardExceptions) {
407 throw $e;
408 }
409 return NULL;
410 }
411
412 return $nitro;
413 }
414
415 return NULL;
416 }
417
418 public function dataDirExists() {
419 return defined("NITROPACK_DATA_DIR") && is_dir(NITROPACK_DATA_DIR); // TODO: Convert this to use the Filesystem abstraction for better Redis support
420 }
421
422 public function initDataDir() {
423 return $this->dataDirExists() || @mkdir(NITROPACK_DATA_DIR, 0755, true); // TODO: Convert this to use the Filesystem abstraction for better Redis support
424 }
425
426 public function pluginDataDirExists() {
427 return defined("NITROPACK_PLUGIN_DATA_DIR") && is_dir(NITROPACK_PLUGIN_DATA_DIR); // TODO: Convert this to use the Filesystem abstraction for better Redis support
428 }
429
430 public function initPluginDataDir() {
431 return $this->pluginDataDirExists() || @mkdir(NITROPACK_PLUGIN_DATA_DIR, 0755, true); // TODO: Convert this to use the Filesystem abstraction for better Redis support
432 }
433
434 public function setDisabledReason($reason) {
435 $this->disabledReason = $reason;
436 nitropack_header("X-Nitro-Disabled-Reason: $reason");
437 }
438
439 public function getDisabledReason() {
440 return $this->disabledReason;
441 }
442
443 public function setPageType($type) {
444 $this->pageType = $type;
445 }
446
447 public function getPageType() {
448 return $this->pageType;
449 }
450
451 /**
452 * Get current url
453 *
454 * @return string The current url
455 */
456 public function getCurrentUrl() {
457
458 if ( defined('NITROPACK_HOST') ) {
459
460 return NITROPACK_HOST;
461 }
462
463 if (! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] )) {
464 $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
465 } else {
466 $host = !empty($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : "";
467 }
468
469 $uri = !empty($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"] : "";
470 $currentUrl = $host . $uri;
471
472 if (empty($currentUrl) || (defined( 'WP_CLI' ) && WP_CLI && trim($currentUrl) == "localhost")) {
473
474 if (function_exists('get_site_url')) {
475 $host = apply_filters('nitropack_current_host', get_site_url());
476 } elseif (function_exists('get_option')) {
477 $host = apply_filters('nitropack_current_host', get_option('siteurl'));
478 }
479
480 if ($host != '') {
481 $site_url = parse_url($host);
482 if (is_array($site_url) && isset($site_url["host"]) && !empty($site_url["host"])) {
483 $currentUrl = $site_url["host"];
484 }
485 }
486 }
487
488 if (stripos($currentUrl, "www.") === 0) {
489 $currentUrl = substr($currentUrl, 4);
490 }
491
492 return $currentUrl;
493 }
494 }
495