PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.15.2
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.15.2
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
491 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 private $sdkObjects;
144 private $disabledReason;
145 private $pageType;
146
147 public $Config;
148 public $Notifications;
149
150 public function __construct() {
151 $this->Config = new Config($this);
152 $this->Notifications = new Notifications($this);
153 $this->sdkObjects = array();
154 $this->disabledReason = NULL;
155 $this->pageType = NULL;
156 }
157
158 public function getDistribution() {
159 $dist = "regular";
160 $dbDist = NULL;
161
162 try {
163 if (function_exists("get_option")) {
164 $dbDist = get_option("nitropack-distribution", NULL);
165 }
166
167 if ($this->isConnected()) {
168 $sdk = $this->getSdk();
169 if (!$sdk) return $dbDist ? $dbDist : $dist;
170
171 $config = $sdk->getConfig();
172 if ($config) {
173 $dist = $config->Distribution;
174 }
175 } else if ($dbDist !== NULL) {
176 $dist = $dbDist;
177 }
178
179 if ($dbDist != $dist && function_exists("update_option")) {
180 update_option("nitropack-distribution", $dist);
181 }
182
183 return $dist;
184 } catch (Exception $e) {
185 return $dist;
186 }
187 }
188
189 public function getSiteConfig() {
190 $siteConfig = null;
191 $npConfig = $this->Config->get();
192 $currentUrl = $this -> getCurrentUrl();
193
194 $matchLength = 0;
195
196 foreach ($npConfig as $siteUrl => $config) {
197 if (stripos($siteUrl, "www.") === 0) {
198 $siteUrl = substr($siteUrl, 4);
199 }
200
201 if (stripos($currentUrl, $siteUrl) === 0 && strlen($siteUrl) > $matchLength) {
202 $siteConfig = $config;
203 $matchLength = strlen($siteUrl);
204 }
205 }
206
207 if (!$siteConfig) {
208 $matchLength = 0;
209 foreach ($npConfig as $siteUrl => $config) {
210 if (isset($config['additional_domains'])) {
211 foreach ($config['additional_domains'] as $additionalDomain) {
212 if (stripos($additionalDomain, "www.") === 0) {
213 $additionalDomain = substr($additionalDomain, 4);
214 }
215
216 if (stripos($currentUrl, $additionalDomain) === 0 && strlen($additionalDomain) > $matchLength) {
217 $siteConfig = $config;
218 $matchLength = strlen($additionalDomain);
219 }
220 }
221 }
222 }
223 }
224
225 return $siteConfig;
226 }
227
228 public function getSiteId() {
229 $siteConfig = $this->getSiteConfig();
230 return $siteConfig ? $siteConfig["siteId"] : NULL;
231 }
232
233 public function getSiteSecret() {
234 $siteConfig = $this->getSiteConfig();
235 return $siteConfig ? $siteConfig["siteSecret"] : NULL;
236 }
237
238 /**
239 * Bear in mind that get_home_url() is not defined in the context of advanced_cache.php
240 * so this will throw a fatal error if you call it at that point!
241 */
242 public static function getConfigKey() {
243 return preg_replace("/^https?:\/\/(.*)/", "$1", get_home_url());
244 }
245
246 public function getAdditionalDomains($siteId, $siteSecret) {
247 if (null !== $nitro = $this->getSdk($siteId, $siteSecret)) {
248 $config = $nitro->getConfig();
249 if (!property_exists($config->AdditionalDomains, 'Domains')) {
250 $nitro->fetchConfig();
251 }
252 return $config->AdditionalDomains->Domains;
253 }
254
255 return [];
256 }
257
258 public function isConnected() {
259 return !empty($this->getSiteId()) && !empty($this->getSiteSecret());
260 }
261
262 public function updateCurrentBlogConfig($siteId, $siteSecret, $blogId, $enableCompression = null) {
263 if ($enableCompression === null) {
264 $enableCompression = (get_option('nitropack-enableCompression') == 1);
265 }
266
267 $webhookToken = get_option('nitropack-webhookToken');
268 $hosting = nitropack_detect_hosting();
269
270 $home_url = get_home_url();
271 $admin_url = admin_url();
272 $alwaysBuffer = defined("NITROPACK_ALWAYS_BUFFER") ? NITROPACK_ALWAYS_BUFFER : true;
273 $configKey = self::getConfigKey();
274 $staticConfig = $this->Config->get();
275 $staticConfig[$configKey] = array(
276 "siteId" => $siteId,
277 "siteSecret" => $siteSecret,
278 "blogId" => $blogId,
279 "compression" => $enableCompression,
280 "webhookToken" => $webhookToken,
281 "home_url" => $home_url,
282 "admin_url" => $admin_url,
283 "hosting" => $hosting,
284 "alwaysBuffer" => $alwaysBuffer,
285 "isEzoicActive" => \NitroPack\Integration\Plugin\Ezoic::isActive(),
286 "isApoActive" => \NitroPack\Integration\Plugin\Cloudflare::isApoActive(),
287 "isNginxHelperActive" => \NitroPack\Integration\Plugin\NginxHelper::isActive(),
288 "isLateIntegrationInitRequired" => nitropack_is_late_integration_init_required(),
289 "isDlmActive" => \NitroPack\Integration\Plugin\DownloadManager::isActive(),
290 "isWoocommerceCacheHandlerActive" => \NitroPack\Integration\Plugin\WoocommerceCacheHandler::isActive(),
291 "isWoocommerceActive" => \NitroPack\Integration\Plugin\Woocommerce::isActive(),
292 "isAeliaCurrencySwitcherActive" => \NitroPack\Integration\Plugin\AeliaCurrencySwitcher::isActive(),
293 "isGeoTargetingWPActive" => \NitroPack\Integration\Plugin\GeoTargetingWP::isActive(),
294 "dlm_downloading_url" => \NitroPack\Integration\Plugin\DownloadManager::isActive() ? \NitroPack\Integration\Plugin\DownloadManager::downloadingUrl() : NULL,
295 "dlm_download_endpoint" => \NitroPack\Integration\Plugin\DownloadManager::isActive() ? \NitroPack\Integration\Plugin\DownloadManager::downloadEndpoint() : NULL,
296 "pluginVersion" => NITROPACK_VERSION,
297 "options_cache" => [],
298 "additional_domains" => $this->getAdditionalDomains($siteId, $siteSecret),
299 );
300 foreach (self::$optionsToCache as $opt) {
301 if (is_array($opt)) {
302 foreach($opt as $option => $suboption) {
303 if (empty($staticConfig[$configKey]["options_cache"][$option])) {
304 $staticConfig[$configKey]["options_cache"][$option] = [];
305 }
306 $optionValue = get_option($option);
307 if (!empty($optionValue)) {
308 $staticConfig[$configKey]["options_cache"][$option][$suboption] = $optionValue[$suboption];
309 } else {
310 $staticConfig[$configKey]["options_cache"][$option][$suboption] = null;
311 }
312 }
313 } else {
314 $staticConfig[$configKey]["options_cache"][$opt] = get_option($opt);
315 }
316 }
317 $configSetResult = $this->Config->set($staticConfig);
318
319 if (\NitroPack\Integration\Plugin\AeliaCurrencySwitcher::isActive()) {
320 try {
321 \NitroPack\Integration\Plugin\AeliaCurrencySwitcher::configureVariationCookies();
322 } catch (\Exception $e) {
323 // TODO: Log this error
324 }
325 }
326 if (\NitroPack\Integration\Plugin\GeoTargetingWP::isActive()) {
327 try {
328 \NitroPack\Integration\Plugin\GeoTargetingWP::configureVariationCookies();
329 } catch (\Exception $e) {
330 // TODO: Log this error
331 }
332 }
333
334 return $configSetResult;
335 }
336
337 public function unsetCurrentBlogConfig() {
338 $configKey = self::getConfigKey();
339 $staticConfig = $this->Config->get();
340 if (!empty($staticConfig[$configKey])) {
341 unset($staticConfig[$configKey]);
342 return $this->Config->set($staticConfig);
343 }
344
345 return true;
346 }
347
348 public function resetSdkInstances() {
349 $this->sdkObjects = [];
350 }
351
352 public function getSdk($siteId = null, $siteSecret = null, $urlOverride = NULL, $forwardExceptions = false) {
353 $siteConfig = $this->getSiteConfig();
354
355 $siteId = $siteId ?: (!empty($siteConfig) ? $siteConfig['siteId'] : NULL);
356 $siteSecret = $siteSecret ?: (!empty($siteConfig) ? $siteConfig['siteSecret'] : NULL);
357
358 if ($siteId && $siteSecret) {
359 try {
360 $userAgent = NULL; // It will be automatically detected by the SDK
361 $dataDir = nitropack_trailingslashit(NITROPACK_DATA_DIR) . $siteId; // dir without a trailing slash, because this is how the SDK expects it
362 $cacheKey = "{$siteId}:{$siteSecret}:{$dataDir}";
363
364 if ($urlOverride) {
365 $cacheKey .= ":{$urlOverride}";
366 }
367
368 if (!empty($this->sdkObjects[$cacheKey])) {
369 $nitro = $this->sdkObjects[$cacheKey];
370 } else {
371 if (!defined("NP_COOKIE_FILTER")) {
372 \NitroPack\SDK\NitroPack::addCookieFilter("nitropack_filter_non_original_cookies");
373 define("NP_COOKIE_FILTER", true);
374 do_action('np_set_cookie_filter');
375 }
376 if (!defined("NP_STORAGE_CONFIGURED")) {
377 if (defined("NITROPACK_USE_REDIS") && NITROPACK_USE_REDIS) {
378 \NitroPack\SDK\Filesystem::setStorageDriver(new \NitroPack\SDK\StorageDriver\Redis(
379 NITROPACK_REDIS_HOST,
380 NITROPACK_REDIS_PORT,
381 NITROPACK_REDIS_PASS,
382 NITROPACK_REDIS_DB
383 ));
384 }
385 define("NP_STORAGE_CONFIGURED", true);
386 }
387
388 if (!defined('NP_GEOLOCATION_PREFIX_DEFINED')) {
389 do_action('set_nitropack_geo_cache_prefix');
390 define('NP_GEOLOCATION_PREFIX_DEFINED', true);
391 }
392
393 if (defined("NITROPACK_CUSTOM_CACHE_PREFIX") && !defined('NP_CUSTOM_CACHE_PREFIX_SET')) {
394 \NitroPack\SDK\NitroPack::addCustomCachePrefix(NITROPACK_CUSTOM_CACHE_PREFIX);
395 define('NP_CUSTOM_CACHE_PREFIX_SET', true);
396 }
397
398 $nitro = new \NitroPack\SDK\NitroPack($siteId, $siteSecret, $userAgent, $urlOverride, $dataDir);
399 $this->sdkObjects[$cacheKey] = $nitro;
400 }
401 } catch (\Exception $e) {
402 if ($forwardExceptions) {
403 throw $e;
404 }
405 return NULL;
406 }
407
408 return $nitro;
409 }
410
411 return NULL;
412 }
413
414 public function dataDirExists() {
415 return defined("NITROPACK_DATA_DIR") && is_dir(NITROPACK_DATA_DIR); // TODO: Convert this to use the Filesystem abstraction for better Redis support
416 }
417
418 public function initDataDir() {
419 return $this->dataDirExists() || @mkdir(NITROPACK_DATA_DIR, 0755, true); // TODO: Convert this to use the Filesystem abstraction for better Redis support
420 }
421
422 public function pluginDataDirExists() {
423 return defined("NITROPACK_PLUGIN_DATA_DIR") && is_dir(NITROPACK_PLUGIN_DATA_DIR); // TODO: Convert this to use the Filesystem abstraction for better Redis support
424 }
425
426 public function initPluginDataDir() {
427 return $this->pluginDataDirExists() || @mkdir(NITROPACK_PLUGIN_DATA_DIR, 0755, true); // TODO: Convert this to use the Filesystem abstraction for better Redis support
428 }
429
430 public function setDisabledReason($reason) {
431 $this->disabledReason = $reason;
432 nitropack_header("X-Nitro-Disabled-Reason: $reason");
433 }
434
435 public function getDisabledReason() {
436 return $this->disabledReason;
437 }
438
439 public function setPageType($type) {
440 $this->pageType = $type;
441 }
442
443 public function getPageType() {
444 return $this->pageType;
445 }
446
447 /**
448 * Get current url
449 *
450 * @return string The current url
451 */
452 public function getCurrentUrl() {
453
454 if ( defined('NITROPACK_HOST') ) {
455
456 return NITROPACK_HOST;
457 }
458
459 if (! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] )) {
460 $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
461 } else {
462 $host = !empty($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : "";
463 }
464
465 $uri = !empty($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"] : "";
466 $currentUrl = $host . $uri;
467
468 if (empty($currentUrl) || (defined( 'WP_CLI' ) && WP_CLI && trim($currentUrl) == "localhost")) {
469
470 if (function_exists('get_site_url')) {
471 $host = apply_filters('nitropack_current_host', get_site_url());
472 } elseif (function_exists('get_option')) {
473 $host = apply_filters('nitropack_current_host', get_option('siteurl'));
474 }
475
476 if ($host != '') {
477 $site_url = parse_url($host);
478 if (is_array($site_url) && isset($site_url["host"]) && !empty($site_url["host"])) {
479 $currentUrl = $site_url["host"];
480 }
481 }
482 }
483
484 if (stripos($currentUrl, "www.") === 0) {
485 $currentUrl = substr($currentUrl, 4);
486 }
487
488 return $currentUrl;
489 }
490 }
491