PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.5.19
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.5.19
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 / functions.php
nitropack Last commit date
classes 3 years ago languages 3 years ago nitropack-sdk 3 years ago view 3 years ago advanced-cache.php 3 years ago batcache-compat.php 4 years ago cf-helper.php 5 years ago constants.php 3 years ago diagnostics.php 3 years ago functions.php 3 years ago helpers.php 3 years ago integrations.php 4 years ago main.php 3 years ago readme.txt 3 years ago uninstall.php 4 years ago wp-cli.php 3 years ago
functions.php
3348 lines
1 <?php
2
3 defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
4
5 $np_basePath = dirname(__FILE__) . '/';
6 require_once $np_basePath . 'constants.php';
7 require_once $np_basePath . 'nitropack-sdk/autoload.php';
8
9 $np_originalRequestCookies = $_COOKIE;
10 $np_customExpirationTimes = array();
11 $np_queriedObj = NULL;
12 $np_loggedPurges = array();
13 $np_loggedInvalidations = array();
14 $np_loggedWarmups = array();
15 $np_integrationSetupEvent = "muplugins_loaded";
16
17 function nitropack_is_logged_in() {
18 $loginCookies = array(defined('NITROPACK_LOGGED_IN_COOKIE') ? NITROPACK_LOGGED_IN_COOKIE : (defined('LOGGED_IN_COOKIE') ? LOGGED_IN_COOKIE : ''));
19 foreach ($loginCookies as $loginCookie) {
20 if (!empty($_COOKIE[$loginCookie])) {
21 return true;
22 }
23 }
24 $cookieStr = implode("|", array_keys($_COOKIE));
25 return strpos($cookieStr, "wordpress_logged_in_") !== false;
26 }
27
28 function nitropack_passes_cookie_requirements() {
29 $isUserLoggedIn = nitropack_is_logged_in();
30 $cookieStr = implode("|", array_keys($_COOKIE));
31 $safeCookie = (
32 (strpos($cookieStr, "comment_author") === false || !!get_nitropack()->setDisabledReason("comment author"))
33 && (strpos($cookieStr, "wp-postpass_") === false || !!get_nitropack()->setDisabledReason("password protected page"))
34 );
35
36 $isItemsInCart = !empty($_COOKIE["woocommerce_items_in_cart"]);
37 $nitro = get_nitropack_sdk();
38 $useAccountOverride = $nitro !== NULL && $nitro->isStatefulCacheSatisfied("account");
39 $useCartOverride = nitropack_is_cart_cache_active();
40
41 if ($isUserLoggedIn && !$useAccountOverride) {
42 get_nitropack()->setDisabledReason("logged in");
43 }
44
45 if ($isItemsInCart && !$useCartOverride) {
46 get_nitropack()->setDisabledReason("items in cart");
47 }
48
49 // allow registering filters to "nitropack_passes_cookie_requirements"
50 return apply_filters("nitropack_passes_cookie_requirements", $safeCookie && (!$isItemsInCart || $useCartOverride) && (!$isUserLoggedIn || $useAccountOverride));
51 }
52
53 function nitropack_activate() {
54 nitropack_set_wp_cache_const(true);
55 $htaccessFile = nitropack_trailingslashit(NITROPACK_DATA_DIR) . ".htaccess";
56 if (!file_exists($htaccessFile) && get_nitropack()->initDataDir()) {
57 file_put_contents($htaccessFile, "deny from all");
58 }
59 nitropack_install_advanced_cache();
60
61 // Htaccess mods need to happen after installing the advanced cache file so the healthcheck can execute fast
62 nitropack_set_htaccess_rules(true);
63
64 try {
65 do_action('nitropack_integration_purge_all');
66 } catch (\Exception $e) {
67 // Exception while signaling our 3rd party integration addons to purge their cache
68 }
69
70 if (get_nitropack()->isConnected()) {
71 nitropack_event("enable_extension");
72 } else {
73 setcookie("nitropack_after_activate_notice", 1, time() + 3600);
74 }
75
76 if (function_exists("opcache_reset")) {
77 opcache_reset();
78 }
79 }
80
81 function nitropack_deactivate() {
82 nitropack_set_htaccess_rules(false);
83 nitropack_set_wp_cache_const(false);
84 nitropack_uninstall_advanced_cache();
85
86 try {
87 do_action('nitropack_integration_purge_all');
88 } catch (\Exception $e) {
89 // Exception while signaling our 3rd party integration addons to purge their cache
90 }
91
92 if (get_nitropack()->isConnected()) {
93 nitropack_event("disable_extension");
94 }
95
96 if (function_exists("opcache_reset")) {
97 opcache_reset();
98 }
99 }
100
101 function nitropack_install_advanced_cache() {
102 if (nitropack_is_conflicting_plugin_active()) return false;
103 if (!nitropack_is_advanced_cache_allowed()) return false;
104
105 $templatePath = nitropack_trailingslashit(__DIR__) . "advanced-cache.php";
106 if (file_exists($templatePath)) {
107 $contents = file_get_contents($templatePath);
108 $contents = str_replace("/*NITROPACK_FUNCTIONS_FILE*/", __FILE__, $contents);
109 $contents = str_replace("/*NITROPACK_ABSPATH*/", ABSPATH, $contents);
110 $contents = str_replace("/*LOGIN_COOKIES*/", defined("LOGGED_IN_COOKIE") ? LOGGED_IN_COOKIE : "", $contents);
111 $contents = str_replace("/*NP_VERSION*/", NITROPACK_VERSION, $contents);
112
113 $advancedCacheFile = nitropack_trailingslashit(WP_CONTENT_DIR) . 'advanced-cache.php';
114 if (WP_DEBUG) {
115 return file_put_contents($advancedCacheFile, $contents);
116 } else {
117 return @file_put_contents($advancedCacheFile, $contents);
118 }
119 }
120 }
121
122 function nitropack_uninstall_advanced_cache() {
123 $advancedCacheFile = nitropack_trailingslashit(WP_CONTENT_DIR) . 'advanced-cache.php';
124 if (file_exists($advancedCacheFile)) {
125 if (WP_DEBUG) {
126 return file_put_contents($advancedCacheFile, "");
127 } else {
128 return @file_put_contents($advancedCacheFile, "");
129 }
130 }
131 }
132
133 function nitropack_set_wp_cache_const($status) {
134 if (\NitroPack\Integration\Hosting\Flywheel::detect()) { // Flywheel: This is configured throught the FW control panel
135 return true;
136 }
137
138 if (\NitroPack\Integration\Hosting\Pressable::detect()) { // Pressable: We need to deal with Batcache here
139 return nitropack_set_batcache_compat($status);
140 }
141
142 $configFilePath = nitropack_get_wpconfig_path();
143 if (!$configFilePath) return false;
144
145 $newVal = sprintf("define( 'WP_CACHE', %s /* Modified by NitroPack */ );\n", ($status ? "true" : "false") );
146 $replacementVal = sprintf(" %s /* Modified by NitroPack */ ", ($status ? "true" : "false") );
147 $lines = file($configFilePath);
148
149 if (empty($lines)) return false;
150
151 $wpCacheFound = false;
152 $phpOpeningTagLine = false;
153
154 foreach ($lines as $lineIndex => &$line) {
155 if (strpos($line, "<?php") !== false && strpos($line, "?>") === false) {
156 $phpOpeningTagLine = $lineIndex;
157 }
158
159 if (!$wpCacheFound && preg_match("/define\s*\(\s*['\"](.*?)['\"].?,(.*?)\)/", $line, $matches)) {
160 if ($matches[1] == "WP_CACHE") {
161 $line = str_replace($matches[2], $replacementVal, $line);
162 $wpCacheFound = true;
163 }
164 }
165
166 if ($phpOpeningTagLine !== false && $wpCacheFound !== false) break;
167 }
168
169 if (!$wpCacheFound) {
170 if (!$status) return true; // No need to modify the file at all
171
172 if ($phpOpeningTagLine !== false) {
173 array_splice($lines, $phpOpeningTagLine + 1, 0, [$newVal]);
174 } else {
175 array_unshift($lines, "<?php " . trim($newVal) . " ?>\n");
176 }
177 }
178
179 return WP_DEBUG ? file_put_contents($configFilePath, implode("", $lines)) : @file_put_contents($configFilePath, implode("", $lines));
180 }
181
182 function nitropack_set_htaccess_rules($status) {
183 if (!apply_filters('nitropack_should_modify_htaccess', false)) return true;
184
185 $htaccessFilePath = nitropack_get_htaccess_path();
186 if (!$htaccessFilePath) return false;
187
188 $htaccessBackupFilePath = $htaccessFilePath . ".nitrobackup";
189 $backupExists = WP_DEBUG ? file_exists($htaccessBackupFilePath) : @file_exists($htaccessBackupFilePath);
190 if (!$backupExists) {
191 $isBackupSuccess = WP_DEBUG ? copy($htaccessFilePath, $htaccessBackupFilePath) : @copy($htaccessFilePath, $htaccessBackupFilePath);
192 if (!$isBackupSuccess) return false;
193 }
194
195 $lines = file($htaccessFilePath);
196 $linesBackup = $lines;
197
198 if (empty($lines)) return false; // We might want to remove this check
199
200 $nitroOpenLine = false;
201 $nitroCloseLine = false;
202
203 foreach ($lines as $lineIndex => &$line) {
204 if (trim($line) == "# BEGIN NITROPACK") {
205 $nitroOpenLine = $lineIndex;
206 }
207
208 if (trim($line) == "# END NITROPACK") {
209 $nitroCloseLine = $lineIndex;
210 }
211 }
212
213 $nitroLines = [];
214
215 if ( // We either didn't find the NitroPack markers or we found both in the correct order
216 ($nitroOpenLine === false && $nitroCloseLine === false) ||
217 ($nitroOpenLine !== false && $nitroCloseLine !== false && $nitroCloseLine > $nitroOpenLine)
218 ) {
219 $nitroLines[] = "# BEGIN NITROPACK";
220 if ($status) {
221 $rules = apply_filters("nitropack_htaccess_rules", []);
222
223 if (is_string($rules)) {
224 $rules = explode("\n", $rules);
225 }
226
227 if (is_array($rules)) {
228 $nitroLines = array_merge($nitroLines, $rules);
229 }
230 }
231 $nitroLines[] = "# END NITROPACK";
232 $nitroLines = array_map(function($line) { return trim($line) . "\n"; }, $nitroLines);
233
234 // Begin .htaccess modification
235 $offset = $nitroOpenLine !== false ? $nitroOpenLine : 0;
236 $length = $nitroOpenLine !== false ? $nitroCloseLine - $nitroOpenLine + 1 : 0;
237 array_splice($lines, $offset, $length, $nitroLines);
238 $writeResult = WP_DEBUG ? file_put_contents($htaccessFilePath, implode("", $lines)) : @file_put_contents($htaccessFilePath, implode("", $lines));
239 if ($writeResult) {
240 $homeUrl = NULL;
241 $siteConfig = get_nitropack()->getSiteConfig();
242
243 if ($siteConfig && !empty($siteConfig["home_url"])) {
244 $homeUrl = $siteConfig["home_url"];
245 } else if (function_exists(get_home_url())) {
246 $homeUrl = get_home_url();
247 }
248
249 if ($homeUrl) {
250 $homeUrl .= (strpos($homeUrl, "?") === false ? "?" : "&") . "nitroHealthcheck=1";
251 try {
252 $client = new \NitroPack\HttpClient\HttpClient($homeUrl);
253 $client->timeout = 5;
254 $client->setHeader("Accept", "text/html");
255 $client->fetch();
256 if ($client->getStatusCode() != 200) {
257 // Restore the initial version of the file
258 WP_DEBUG ? file_put_contents($htaccessFilePath, implode("", $linesBackup)) : @file_put_contents($htaccessFilePath, implode("", $linesBackup));
259 return false;
260 }
261 } catch (\Exception $e) {
262 return false;
263 // Unfortunately we can't be certain whether an issue appeared due to the .htaccess mods
264 // There are no known cases of this happening, so it's fairly safe to assume that all is fine
265 // There are server setups which do not allow loopback requests, which is the more likely reason to end up here
266 // However we can't be certain which one it is, so we are taking the safer approach
267 }
268 } else {
269 return false;
270 }
271 }
272 return $writeResult;
273 }
274
275 return true;
276 }
277
278 function nitropack_set_batcache_compat($status) {
279 $currentCompatStatus = defined("NITROPACK_BATCACHE_COMPAT") && NITROPACK_BATCACHE_COMPAT;
280 if ($currentCompatStatus === $status) return true;
281
282 $configFilePath = nitropack_get_wpconfig_path();
283 if (!$configFilePath) return false;
284
285 $batCacheFilePath = NITROPACK_PLUGIN_DIR . "batcache-compat.php";
286 $compatInclude = sprintf("if (file_exists(\"%s\")) { require_once \"%s\"; } // NitroPack compatibility with Batcache\n", $batCacheFilePath, $batCacheFilePath);
287 $lines = file($configFilePath);
288
289 if (empty($lines)) return false;
290
291 foreach ($lines as $lineIndex => &$line) {
292 if (preg_match("/nitropack.*?batcache/i", $line)) {
293 $line = "//REMOVE AT FILTER";
294 }
295 }
296
297 $newLines = array_filter($lines, function($line) { return $line != "//REMOVE AT FILTER";});
298
299 if ($status) {
300 $phpOpeningTagLine = false;
301
302 unset($line);
303 foreach ($newLines as $lineIndex => $line) {
304 if (strpos($line, "<?php") !== false && strpos($line, "?>") === false) {
305 $phpOpeningTagLine = $lineIndex;
306 break;
307 }
308 }
309
310 if ($phpOpeningTagLine !== false) {
311 array_splice($newLines, $phpOpeningTagLine + 1, 0, [$compatInclude]);
312 } else {
313 array_unshift($newLines, "<?php " . trim($compatInclude) . " ?>\n");
314 }
315 }
316
317 return WP_DEBUG ? file_put_contents($configFilePath, implode("", $newLines)) : @file_put_contents($configFilePath, implode("", $newLines));
318 }
319
320 function is_valid_nitropack_webhook() {
321 return !empty($_GET["nitroWebhook"]) && !empty($_GET["token"]) && nitropack_validate_webhook_token($_GET["token"]);
322 }
323
324 function is_valid_nitropack_beacon() {
325 if (!isset($_POST["nitroBeaconUrl"]) || !isset($_POST["nitroBeaconHash"])) return false;
326
327 $siteConfig = nitropack_get_site_config();
328 if (!$siteConfig || empty($siteConfig["siteSecret"])) return false;
329
330 if (function_exists("hash_hmac") && function_exists("hash_equals")) {
331 $url = base64_decode($_POST["nitroBeaconUrl"]);
332 $cookiesJson = !empty($_POST["nitroBeaconCookies"]) ? base64_decode($_POST["nitroBeaconCookies"]) : ""; // We need to fall back to empty string to remain backwards compatible. Otherwise cache files invalidated before an upgrade will never get updated :(
333 $layout = !empty($_POST["layout"]) ? $_POST["layout"] : "";
334 $localHash = hash_hmac("sha512", $url.$cookiesJson.$layout, $siteConfig["siteSecret"]);
335 return hash_equals($_POST["nitroBeaconHash"], $localHash);
336 } else {
337 return !empty($_POST["nitroBeaconUrl"]);
338 }
339 }
340
341 function nitropack_handle_beacon() {
342 global $np_originalRequestCookies;
343 if (!defined("NITROPACK_BEACON_HANDLED")) {
344 define("NITROPACK_BEACON_HANDLED", 1);
345 } else {
346 return;
347 }
348
349 $siteConfig = nitropack_get_site_config();
350 if ($siteConfig && !empty($siteConfig["siteId"]) && !empty($siteConfig["siteSecret"]) && !empty($_POST["nitroBeaconUrl"])) {
351 $url = base64_decode($_POST["nitroBeaconUrl"]);
352
353 if (!empty($_POST["nitroBeaconCookies"])) {
354 $np_originalRequestCookies = json_decode(base64_decode($_POST["nitroBeaconCookies"]), true);
355 }
356
357 if (null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"], $url) ) {
358 try {
359 $hasLocalCache = $nitro->hasLocalCache(false);
360 $needsHeartbeat = nitropack_is_heartbeat_needed();
361 $proxyPurgeOnly = !empty($_POST["proxyPurgeOnly"]);
362 $layout = !empty($_POST["layout"]) ? $_POST["layout"] : "default";
363 $output = "";
364
365 if (!$proxyPurgeOnly) {
366 if (!$hasLocalCache) {
367 nitropack_header("X-Nitro-Beacon: FORWARD");
368 try {
369 $hasCache = $nitro->hasRemoteCache($layout, false); // Download the new cache file
370 $hasLocalCache = $hasCache;
371 $output = sprintf("Cache %s", $hasCache ? "fetched" : "requested");
372 } catch (\Exception $e) {
373 // not a critical error, do nothing
374 }
375 } else {
376 nitropack_header("X-Nitro-Beacon: SKIP");
377 $output = sprintf("Cache exists already");
378 }
379 }
380
381 if ($hasLocalCache || $proxyPurgeOnly/* || $needsHeartbeat*/) { // proxyPurgeOnly is set for unsupported browsers, in which case we need to purge the cache regardless of the existence of local NP cache
382 nitropack_header("X-Nitro-Proxy-Purge: true");
383 $nitro->purgeProxyCache($url);
384 do_action('nitropack_integration_purge_url', $url);
385 }
386
387 \NitroPack\Integration::onShutdown(function() use ($output) {
388 echo $output;
389 });
390 } catch (Exception $e) {
391 // not a critical error, do nothing
392 }
393 }
394 }
395 \NitroPack\Integration::onCriticalInit(function() {
396 exit;
397 });
398 }
399
400 function nitropack_handle_webhook() {
401 if (defined('NITROPACK_DEBUG_MODE')) {
402 do_action('nitropack_debug_webhook', $_REQUEST);
403 }
404 if (!defined("NITROPACK_WEBHOOK_HANDLED")) {
405 define("NITROPACK_WEBHOOK_HANDLED", 1);
406 } else {
407 return;
408 }
409
410 $siteConfig = nitropack_get_site_config();
411 if ($siteConfig && $siteConfig["webhookToken"] == $_GET["token"]) {
412 switch($_GET["nitroWebhook"]) {
413 case "config":
414 nitropack_fetch_config();
415 get_nitropack()->resetSdkInstances(); // This is needed in order to obtain a new SDK instance with the fresh config
416 nitropack_set_htaccess_rules(true);
417 break;
418 case "cache_ready":
419 if (!empty($_POST["url"])) {
420 $readyUrl = nitropack_sanitize_url_input($_POST["url"]);
421
422 if ($readyUrl && null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"], $readyUrl) ) {
423 $hasCache = $nitro->hasRemoteCache("default", false); // Download the new cache file
424 $nitro->purgeProxyCache($readyUrl);
425 do_action('nitropack_integration_purge_url', $readyUrl);
426 }
427 }
428 break;
429 case "cache_clear":
430 $proxyPurgeOnly = !empty($_POST["proxyPurgeOnly"]);
431 if (!empty($_POST["url"])) {
432 $urls = is_array($_POST["url"]) ? $_POST["url"] : array($_POST["url"]);
433 foreach ($urls as $url) {
434 $sanitizedUrl = nitropack_sanitize_url_input($url);
435 if ($proxyPurgeOnly) {
436 if (null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
437 $nitro->purgeProxyCache($sanitizedUrl);
438 }
439 do_action('nitropack_integration_purge_url', $sanitizedUrl);
440 } else {
441 nitropack_sdk_purge_local($sanitizedUrl);
442 }
443 }
444 } else {
445 if ($proxyPurgeOnly) {
446 if (null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
447 $nitro->purgeProxyCache();
448 }
449 do_action('nitropack_integration_purge_all');
450 } else {
451 nitropack_sdk_purge_local();
452 nitropack_sdk_delete_backlog();
453 }
454 }
455 break;
456 }
457 }
458 \NitroPack\Integration::onCriticalInit(function() {
459 exit;
460 });
461 }
462
463 function nitropack_sanitize_url_input($url) {
464 $result = NULL;
465 if (!function_exists("esc_url")) {
466 $sanitizedUrl = filter_var($url, FILTER_SANITIZE_URL);
467 if ($sanitizedUrl !== false && filter_var($sanitizedUrl, FILTER_VALIDATE_URL) !== false) {
468 $result = $sanitizedUrl;
469 }
470 } else if ($validatedUrl = esc_url($url, array("http", "https"), "notdisplay")) {
471 $result = $validatedUrl;
472 }
473
474 return $result;
475 }
476
477 function nitropack_is_amp_page() {
478 return
479 (function_exists('amp_is_request') && amp_is_request() && !get_nitropack()->setDisabledReason("amp page")) ||
480 (function_exists('ampforwp_is_amp_endpoint') && ampforwp_is_amp_endpoint() && !get_nitropack()->setDisabledReason("amp page"));
481 }
482
483 function nitropack_passes_page_requirements($detectIfNoCachedResult = true) {
484 static $cachedResult = NULL;
485 $reduceCheckoutChecks = defined("NITROPACK_REDUCE_CHECKOUT_CHECKS") && NITROPACK_REDUCE_CHECKOUT_CHECKS;
486 $reduceCartChecks = defined("NITROPACK_REDUCE_CART_CHECKS") && NITROPACK_REDUCE_CART_CHECKS;
487
488 if ($cachedResult === NULL && $detectIfNoCachedResult) {
489 $cachedResult = !(
490 ( is_404() && !get_nitropack()->setDisabledReason("404") ) ||
491 ( is_preview() && !get_nitropack()->setDisabledReason("preview page") ) ||
492 ( is_feed() && !get_nitropack()->setDisabledReason("feed") ) ||
493 ( is_comment_feed() && !get_nitropack()->setDisabledReason("comment feed") ) ||
494 ( is_trackback() && !get_nitropack()->setDisabledReason("trackback") ) ||
495 ( is_user_logged_in() && !get_nitropack()->setDisabledReason("logged in") ) ||
496 ( is_search() && !get_nitropack()->setDisabledReason("search") ) ||
497 ( nitropack_is_ajax() && !get_nitropack()->setDisabledReason("ajax") ) ||
498 ( nitropack_is_post() && !get_nitropack()->setDisabledReason("post request") ) ||
499 ( nitropack_is_xmlrpc() && !get_nitropack()->setDisabledReason("xmlrpc") ) ||
500 ( nitropack_is_robots() && !get_nitropack()->setDisabledReason("robots") ) ||
501 nitropack_is_amp_page() ||
502 !nitropack_is_allowed_request() ||
503 ( nitropack_is_wp_cron() && !get_nitropack()->setDisabledReason("doing cron") ) || // CRON request
504 ( nitropack_is_wp_cli() ) || // CLI request
505 ( defined('WC_PLUGIN_FILE') && (is_page( 'cart' ) || ( !$reduceCartChecks && is_cart()) ) && !get_nitropack()->setDisabledReason("cart page") ) || // WooCommerce
506 ( defined('WC_PLUGIN_FILE') && (is_page( 'checkout' ) || ( !$reduceCheckoutChecks && is_checkout()) ) && !get_nitropack()->setDisabledReason("checkout page") ) || // WooCommerce
507 ( defined('WC_PLUGIN_FILE') && is_account_page() && !get_nitropack()->setDisabledReason("account page") ) // WooCommerce
508 );
509 }
510
511 return $cachedResult;
512 }
513
514 function nitropack_is_home() {
515 return is_front_page() || is_home();
516 }
517
518 function nitropack_is_archive() {
519 return apply_filters("nitropack_is_archive_page", is_author() || is_archive());
520 }
521
522 function nitropack_is_allowed_request() {
523 global $np_queriedObj;
524 $cacheableObjectTypes = nitropack_get_cacheable_object_types();
525 if (is_array($cacheableObjectTypes)) {
526 if (nitropack_is_home()) {
527 if (!in_array('home', $cacheableObjectTypes)) {
528 get_nitropack()->setDisabledReason("page type not allowed (home)");
529 return false;
530 }
531 } else {
532 if (is_tax() || is_category() || is_tag()) {
533 $np_queriedObj = get_queried_object();
534 if (!empty($np_queriedObj) && !in_array($np_queriedObj->taxonomy, $cacheableObjectTypes)) {
535 get_nitropack()->setDisabledReason("page type not allowed ({$np_queriedObj->taxonomy})");
536 return false;
537 }
538 } else {
539 if (nitropack_is_archive()) {
540 if (!in_array('archive', $cacheableObjectTypes)) {
541 get_nitropack()->setDisabledReason("page type not allowed (archive)");
542 return false;
543 }
544 } else {
545 $postType = get_post_type();
546 if (!empty($postType) && !in_array($postType, $cacheableObjectTypes)) {
547 get_nitropack()->setDisabledReason("page type not allowed ($postType)");
548 return false;
549 }
550 }
551 }
552 }
553 }
554
555 if (null !== $nitro = get_nitropack_sdk() ) {
556 return
557 ( $nitro->isAllowedUrl($nitro->getUrl()) || get_nitropack()->setDisabledReason("url not allowed") ) &&
558 ( $nitro->isAllowedRequest(true) || get_nitropack()->setDisabledReason("request type not allowed") );
559 }
560
561 get_nitropack()->setDisabledReason("site not connected");
562 return false;
563 }
564
565 function nitropack_is_ajax() {
566 return
567 (function_exists("wp_doing_ajax") && wp_doing_ajax()) ||
568 (defined('DOING_AJAX') && DOING_AJAX) ||
569 (!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest") ||
570 (!empty($_SERVER["REQUEST_URI"]) && basename($_SERVER["REQUEST_URI"]) == "admin-ajax.php") ||
571 !empty($_GET["wc-ajax"]);
572 }
573
574 /**
575 * Checking if the current request is wp-cli request
576 *
577 * @return bool
578 */
579 function nitropack_is_wp_cli() {
580 return defined("WP_CLI") && WP_CLI;
581 }
582
583 function nitropack_is_wp_cron() {
584 return defined('DOING_CRON') && DOING_CRON;
585 }
586
587 function nitropack_is_rest() {
588 // Source: https://wordpress.stackexchange.com/a/317041
589 $prefix = rest_get_url_prefix( );
590 if (defined('REST_REQUEST') && REST_REQUEST // (#1)
591 || isset($_GET['rest_route']) // (#2)
592 && strpos( trim( $_GET['rest_route'], '\\/' ), $prefix , 0 ) === 0)
593 return true;
594 // (#3)
595 global $wp_rewrite;
596 if ($wp_rewrite === null) $wp_rewrite = new WP_Rewrite();
597
598 // (#4)
599 $rest_url = wp_parse_url( trailingslashit( rest_url( ) ) );
600 $current_url = wp_parse_url( add_query_arg( array( ) ) );
601 return strpos( $current_url['path'], $rest_url['path'], 0 ) === 0;
602 }
603
604 function nitropack_is_post() {
605 return (!empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') || (empty($_SERVER['REQUEST_METHOD']) && !empty($_POST));
606 }
607
608 function nitropack_is_xmlrpc() {
609 return defined('XMLRPC_REQUEST') && XMLRPC_REQUEST;
610 }
611
612 function nitropack_is_robots() {
613 return is_robots() || (!empty($_SERVER["REQUEST_URI"]) && basename(parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH)) === "robots.txt");
614 }
615
616 // IMPORTANT: This function should only be trusted if NitroPack is connected. Otherwise we may not have information about the admin URL in the config file and it may return an incorrect result
617 function nitropack_is_admin() {
618 if ((nitropack_is_ajax() || nitropack_is_rest()) && !empty($_SERVER["HTTP_REFERER"])) {
619 $adminUrl = NULL;
620 $siteConfig = nitropack_get_site_config();
621 if ($siteConfig && !empty($siteConfig["admin_url"])) {
622 $adminUrl = $siteConfig["admin_url"];
623 } else if (function_exists("admin_url")) {
624 $adminUrl = admin_url();
625 } else {
626 return is_admin();
627 }
628
629 return strpos($_SERVER["HTTP_REFERER"], $adminUrl) === 0;
630 } else {
631 return is_admin();
632 }
633 }
634
635 function nitropack_is_warmup_request() {
636 return !empty($_SERVER["HTTP_X_NITRO_WARMUP"]);
637 }
638
639 function nitropack_is_lighthouse_request() {
640 return !empty($_SERVER["HTTP_USER_AGENT"]) && stripos($_SERVER["HTTP_USER_AGENT"], "lighthouse") !== false;
641 }
642
643 function nitropack_is_gtmetrix_request() {
644 return !empty($_SERVER["HTTP_USER_AGENT"]) && stripos($_SERVER["HTTP_USER_AGENT"], "gtmetrix") !== false;
645 }
646
647 function nitropack_is_pingdom_request() {
648 return !empty($_SERVER["HTTP_USER_AGENT"]) && stripos($_SERVER["HTTP_USER_AGENT"], "pingdom") !== false;
649 }
650
651 function nitropack_is_optimizer_request() {
652 return isset($_SERVER["HTTP_X_NITROPACK_REQUEST"]);
653 }
654
655 function nitropack_init() {
656 global $np_queriedObj;
657 nitropack_header('X-Nitro-Cache: MISS');
658 $GLOBALS["NitroPack.tags"] = array();
659
660 if (is_valid_nitropack_webhook()) {
661 nitropack_handle_webhook();
662 } else {
663 if (is_valid_nitropack_beacon()) {
664 nitropack_handle_beacon();
665 } else {
666 /* The following if statement should stay as it is written.
667 * is_archive() can return true if visiting a tax, category or tag page, so is_acrchive must be checked last
668 */
669 if (is_tax() || is_category() || is_tag()) {
670 $np_queriedObj = get_queried_object();
671 get_nitropack()->setPageType($np_queriedObj->taxonomy);
672 } else {
673 $layout = nitropack_get_layout();
674 get_nitropack()->setPageType($layout);
675 }
676
677 add_action('wp_footer', 'nitropack_print_element_override', 9999999);
678 if (!isset($_GET["wpf_action"]) && nitropack_passes_cookie_requirements() && nitropack_passes_page_requirements()) {
679 add_action('wp_footer', 'nitropack_print_beacon_script');
680 add_action('get_footer', 'nitropack_print_beacon_script');
681
682 $active_plugins = apply_filters('active_plugins', get_option('active_plugins'));
683 if (in_array('woocommerce-multilingual/wpml-woocommerce.php', $active_plugins, true) && (!isset($_COOKIE["np_wc_currency"]) || !isset($_COOKIE["np_wc_currency_language"]))) {
684 add_action('woocommerce_init', 'set_wc_cookies');
685 }
686
687 if (nitropack_is_optimizer_request()) { // Only care about tags for requests coming from our service. There is no need to do an API request when handling a standard client request.
688 if (defined('FUSION_BUILDER_VERSION')) {
689 add_filter('do_shortcode_tag', 'nitropack_handle_fusion_builder_conatainer_expiration', 10, 3);
690 add_action('wp_footer', 'nitropack_set_custom_expiration');
691 } else {
692 nitropack_set_custom_expiration();
693 }
694
695 $GLOBALS["NitroPack.tags"]["pageType:" . get_nitropack()->getPageType()] = 1;
696
697 /* The following if statement should stay as it is written.
698 * is_archive() can return true if visiting a tax, category or tag page, so is_acrchive must be checked last
699 */
700 if (is_tax() || is_category() || is_tag()) {
701 $np_queriedObj = get_queried_object();
702 $GLOBALS["NitroPack.tags"]["tax:" . $np_queriedObj->term_taxonomy_id] = 1;
703 } else {
704 if (is_single() || is_page() || is_attachment()) {
705 $singlePost = get_post();
706 if ($singlePost) {
707 $GLOBALS["NitroPack.tags"]["single:" . $singlePost->ID] = 1;
708 }
709 }
710 }
711
712 // Uncomment the code below in case object cache interferes with correct URL taggig
713 // The code below will attempt to temporarily disable using the object cache only for the requests coming from NitroPack
714 //wp_using_ext_object_cache(false);
715 //add_action("pre_get_posts", function($query) {
716 // $query->query_vars["cache_results"] = false;
717 //});
718 //
719 //add_filter("all", function() {
720 // $args = func_get_args();
721 // if (count($args) > 1) {
722 // list($filterName, $value) = func_get_args();
723 // if (preg_match("/^transient_(.*)/", $filterName, $matches) && $value) {
724 // return false;
725 // }
726 // }
727 //}, 10, 2);
728
729 add_filter('post_link', 'nitropack_post_link_listener', 10, 3);
730 add_action('the_post', 'nitropack_handle_the_post');
731 add_action('wp_footer', 'nitropack_log_tags');
732 }
733 } else {
734 nitropack_header("X-Nitro-Disabled: 1");
735 if ((null !== $nitro = get_nitropack_sdk()) && !$nitro->isAllowedBrowser()) { // This clears any proxy cache when a proxy cached non-optimized request due to unsupported browser
736 add_action('wp_footer', 'nitropack_print_beacon_script');
737 add_action('get_footer', 'nitropack_print_beacon_script');
738 }
739 }
740
741 if (!nitropack_is_optimizer_request() && nitropack_passes_page_requirements()) {// This is a cacheable URL
742 add_action('wp_head', 'nitropack_print_telemetry_script');
743 }
744 }
745 }
746 }
747
748 function nitropack_handle_fusion_builder_conatainer_expiration($output, $tag, $attr) {
749 global $np_customExpirationTimes;
750 if ($tag == "fusion_builder_container") {
751 if (!empty($attr["publish_date"]) && !empty($attr["status"]) && in_array($attr["status"], array("published_until", "publish_after"))) {
752 $timezone = get_option('timezone_string');
753 $offset = get_option('gmt_offset');
754 $dt = new DateTime($attr["publish_date"]);
755 if ($timezone) {
756 $timeZone = new DateTimeZone($timezone);
757 $timeZoneOffset = $timeZone->getOffset($dt);
758 } else if ($offset) {
759 $timeZoneOffset = (int)$offset * 3600;
760 }
761 $time = $dt->getTimestamp() - $timeZoneOffset;
762 if ($time > time()) { // We only need to look at future dates
763 $np_customExpirationTimes[] = $time;
764 }
765 }
766 }
767 return $output;
768 }
769
770 function nitropack_set_custom_expiration() {
771 global $np_customExpirationTimes, $wpdb;
772
773 $nextPostTime = NULL;
774 /*$scheduledPostsQuery = new WP_Query(array(
775 'post_status' => 'future',
776 'date_query' => array(
777 array(
778 'column' => 'post_date',
779 'after' => 'now'
780 )
781 ),
782 'posts_per_page' => 1,
783 'orderby' => 'date',
784 'order' => 'ASC'
785 ));*/
786
787 // WP_Query results can be modified by other plugins, which causes issues. This is why we need to run a raw query.
788 // The query below should be equivalent to the query generated by WP_Query above.
789 $unmodifiedPosts = $wpdb->get_results( "SELECT ID, post_date FROM {$wpdb->prefix}posts WHERE
790 {$wpdb->prefix}posts.post_date > '" . date("Y-m-d H:i:s") . "'
791 AND {$wpdb->prefix}posts.post_type = 'post' AND (({$wpdb->prefix}posts.post_status = 'future')) ORDER BY {$wpdb->prefix}posts.post_date ASC LIMIT 0, 1" );
792
793 if (!empty($unmodifiedPosts) && strtotime($unmodifiedPosts[0]->post_date) > time()) {
794 $np_customExpirationTimes[] = strtotime($unmodifiedPosts[0]->post_date);
795 }
796
797 if (!empty($np_customExpirationTimes)) {
798 sort($np_customExpirationTimes, SORT_NUMERIC);
799 nitropack_header("X-Nitro-Expires: " . $np_customExpirationTimes[0]);
800 }
801 }
802
803 function nitropack_print_beacon_script() {
804 if (defined("NITROPACK_BEACON_PRINTED") || !nitropack_passes_page_requirements()) return;
805 define("NITROPACK_BEACON_PRINTED", true);
806 echo apply_filters("nitro_script_output", nitropack_get_beacon_script());
807 }
808
809 function nitropack_get_beacon_script() {
810 $siteConfig = nitropack_get_site_config();
811 if ($siteConfig && !empty($siteConfig["siteId"]) && !empty($siteConfig["siteSecret"])) {
812 if (null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
813 $url = $nitro->getUrl();
814 $cookiesJson = json_encode($nitro->supportedCookiesFilter(NitroPack\SDK\NitroPack::getCookies()));
815 $layout = nitropack_get_layout();
816
817 if (function_exists("hash_hmac") && function_exists("hash_equals")) {
818 $hash = hash_hmac("sha512", $url.$cookiesJson.$layout, $siteConfig["siteSecret"]);
819 } else {
820 $hash = "";
821 }
822 $url = base64_encode($url); // We want only ASCII
823 $cookiesb64 = base64_encode($cookiesJson);
824 $proxyPurgeOnly = !$nitro->isAllowedBrowser();
825
826 return "
827 <script nitro-exclude>
828 if (!window.NITROPACK_STATE || window.NITROPACK_STATE != 'FRESH') {
829 var proxyPurgeOnly = " . ($proxyPurgeOnly ? 1 : 0) . ";
830 if (typeof navigator.sendBeacon !== 'undefined') {
831 var nitroData = new FormData(); nitroData.append('nitroBeaconUrl', '$url'); nitroData.append('nitroBeaconCookies', '$cookiesb64'); nitroData.append('nitroBeaconHash', '$hash'); nitroData.append('proxyPurgeOnly', '$proxyPurgeOnly'); nitroData.append('layout', '$layout'); navigator.sendBeacon(location.href, nitroData);
832 } else {
833 var xhr = new XMLHttpRequest(); xhr.open('POST', location.href, true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('nitroBeaconUrl={$url}&nitroBeaconCookies={$cookiesb64}&nitroBeaconHash={$hash}&proxyPurgeOnly={$proxyPurgeOnly}&layout={$layout}');
834 }
835 }
836 </script>";
837 }
838 }
839 }
840
841 function nitropack_print_cookie_handler_script() {
842 if (defined("NITROPACK_COOKIE_HANDLER_PRINTED")) return;
843 define("NITROPACK_COOKIE_HANDLER_PRINTED", true);
844 echo apply_filters("nitro_script_output", nitropack_get_cookie_handler_script());
845 }
846
847 function nitropack_get_cookie_handler_script() {
848 return "
849 <script nitro-exclude>
850 document.cookie = 'nitroCachedPage=' + (!window.NITROPACK_STATE ? '0' : '1') + '; path=/; SameSite=Lax';
851 </script>";
852 }
853
854 function nitropack_print_telemetry_script() {
855 if (defined("NITROPACK_TELEMETRY_PRINTED")) return;
856 define("NITROPACK_TELEMETRY_PRINTED", true);
857 echo apply_filters("nitro_script_output", nitropack_get_telemetry_meta());
858 echo apply_filters("nitro_script_output", nitropack_get_telemetry_script());
859 }
860
861 function nitropack_get_telemetry_script() {
862 $siteConfig = nitropack_get_site_config();
863 if ($siteConfig && !empty($siteConfig["siteId"]) && !empty($siteConfig["siteSecret"])) {
864 if (null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
865 $config = $nitro->getConfig();
866 if (!empty($config->Telemetry)) {
867 return "<script id='nitro-telemetry'>" . $config->Telemetry . "</script>";
868 }
869 }
870 }
871
872 return "";
873 }
874
875 function nitropack_get_telemetry_meta() {
876 $disabledReason = get_nitropack()->getDisabledReason();
877 $missReason = $disabledReason !== NULL ? $disabledReason : "cache not found";
878 $pageType = get_nitropack()->getPageType();
879 $metaObj = "window.NPTelemetryMetadata={";
880
881 if ($missReason) {
882 $metaObj .= "missReason: (!window.NITROPACK_STATE ? '$missReason' : 'hit'),";
883 }
884
885 if ($pageType) {
886 $metaObj .= "pageType: '$pageType',";
887 }
888
889 $metaObj .= "}";
890
891 return "<script id='nitro-telemetry-meta' nitro-exclude>$metaObj</script>";
892 }
893
894 function nitropack_print_element_override() {
895 return;
896 if (defined("NITROPACK_ELEMENT_OVERRIDE_PRINTED")) return;
897 define("NITROPACK_ELEMENT_OVERRIDE_PRINTED", true);
898 echo apply_filters("nitro_script_output", nitropack_get_element_override_script());
899 }
900
901 function nitropack_get_element_override_script() {
902 $nitro = get_nitropack_sdk();
903 return $nitro !== NULL ? $nitro->getStatefulCacheHandlerScript() : "";
904 }
905
906 function nitropack_has_advanced_cache() {
907 return defined( 'NITROPACK_ADVANCED_CACHE' );
908 }
909
910 function set_wc_cookies() {
911 $wcCurrency = WC()->session->get("client_currency");
912 $wcCurrencyLanguage = WC()->session->get("client_currency_language");
913 if (!$wcCurrency) $wcCurrency = 0;
914 if (!$wcCurrencyLanguage) $wcCurrencyLanguage = 0;
915 setcookie('np_wc_currency', $wcCurrency, time() + (86400 * 7), "/");
916 setcookie('np_wc_currency_language', $wcCurrencyLanguage, time() + (86400 * 7), "/");
917 }
918
919 function nitropack_validate_site_id($siteId) {
920 return preg_match("/^([a-zA-Z]{32})$/", trim($siteId));
921 }
922
923 function nitropack_validate_site_secret($siteSecret) {
924 return preg_match("/^([a-zA-Z0-9]{64})$/", trim($siteSecret));
925 }
926
927 function nitropack_validate_webhook_token($token) {
928 return preg_match("/^([abcdef0-9]{32})$/", strtolower($token));
929 }
930
931 function nitropack_validate_wc_currency($cookieValue) {
932 return preg_match("/^([a-z]{3})$/", strtolower($cookieValue));
933 }
934
935 function nitropack_validate_wc_currency_language($cookieValue) {
936 return preg_match("/^([a-z_\\-]{2,})$/", strtolower($cookieValue));
937 }
938
939 function nitropack_get_default_cacheable_object_types() {
940 $result = array("home", "archive");
941 $postTypes = get_post_types(array('public' => true), 'names');
942 $result = array_merge($result, $postTypes);
943 foreach ($postTypes as $postType) {
944 $result = array_merge($result, get_taxonomies(array('object_type' => array($postType), 'public' => true), 'names'));
945 }
946 return $result;
947 }
948
949 function nitropack_get_object_types() {
950 $objectTypes = get_post_types(array('public' => true), 'objects');
951 $taxonomies = get_taxonomies(array('public' => true), 'objects');
952
953 foreach ($objectTypes as &$objectType) {
954 $objectType->taxonomies = [];
955 foreach ($taxonomies as $tax) {
956 if (in_array($objectType->name, $tax->object_type)) {
957 $objectType->taxonomies[] = $tax;
958 }
959 }
960 }
961
962 return $objectTypes;
963 }
964
965 function nitropack_get_cacheable_object_types() {
966 return apply_filters("nitropack_cacheable_post_types", get_option("nitropack-cacheableObjectTypes", nitropack_get_default_cacheable_object_types()));
967 }
968
969 /** Step 3. */
970 function nitropack_options() {
971 if ( !current_user_can( 'manage_options' ) ) {
972 wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
973 }
974
975 wp_enqueue_style('nitropack_bootstrap_css', plugin_dir_url(__FILE__) . 'view/stylesheet/bootstrap.min.css?np_v=' . NITROPACK_VERSION);
976 wp_enqueue_style('nitropack_css', plugin_dir_url(__FILE__) . 'view/stylesheet/nitropack.css?np_v=' . NITROPACK_VERSION);
977 wp_enqueue_style('nitropack_font-awesome_css', plugin_dir_url(__FILE__) . 'view/stylesheet/fontawesome/font-awesome.min.css?np_v=' . NITROPACK_VERSION, true);
978 wp_enqueue_script('nitropack_bootstrap_js_bundle', plugin_dir_url(__FILE__) . 'view/javascript/bootstrap.bundle.min.js?np_v=' . NITROPACK_VERSION, true);
979 wp_enqueue_script('nitropack_overlay_js', plugin_dir_url(__FILE__) . 'view/javascript/overlay.js?np_v=' . NITROPACK_VERSION, true);
980 wp_enqueue_script('nitropack_embed_js', 'https://nitropack.io/asset/js/embed.js?np_v=' . NITROPACK_VERSION, true);
981 wp_enqueue_script( 'jquery-form' );
982
983 // Manually add home and archive page object
984 $homeCustomObject = new stdClass();
985 $homeCustomObject->name = 'home';
986 $homeCustomObject->label = 'Home';
987 $homeCustomObject->taxonomies = array();
988
989 $archiveCustomObject = new stdClass();
990 $archiveCustomObject->name = 'archive';
991 $archiveCustomObject->label = 'Archive';
992 $archiveCustomObject->taxonomies = array();
993 $objectTypes = array_merge(array('home' => $homeCustomObject, 'archive' => $archiveCustomObject), nitropack_get_object_types());
994
995 $enableCompression = get_option('nitropack-enableCompression');
996 $autoCachePurge = get_option('nitropack-autoCachePurge', 1);
997 $bbCacheSyncPurge = get_option('nitropack-bbCacheSyncPurge', 0);
998 $checkedCompression = get_option('nitropack-checkedCompression');
999 $cacheableObjectTypes = nitropack_get_cacheable_object_types();
1000
1001 if (get_nitropack()->isConnected()) {
1002 $planDetailsUrl = get_nitropack_integration_url("plan_details_json");
1003 $optimizationDetailsUrl = get_nitropack_integration_url("optimization_details_json");
1004 $quickSetupUrl = get_nitropack_integration_url("quicksetup_json");
1005 $quickSetupSaveUrl = get_nitropack_integration_url("quicksetup");
1006
1007 include plugin_dir_path(__FILE__) . nitropack_trailingslashit('view') . 'admin.php';
1008 } else {
1009 include plugin_dir_path(__FILE__) . nitropack_trailingslashit('view') . 'connect.php';
1010 }
1011 }
1012
1013 function nitropack_print_notice($type, $message, $dismissibleId = true) {
1014 if ($dismissibleId) {
1015 if (!empty($_COOKIE["dismissed_notice_" . $dismissibleId])) return;
1016 echo '<div class="notice notice-' . $type . ' is-dismissible" data-dismissible-id="' . $dismissibleId . '">';
1017 } else {
1018 echo '<div class="notice notice-' . $type . '">';
1019 }
1020 echo '<p><strong>NitroPack:</strong> ' . $message . '</p>';
1021 echo '</div>';
1022 }
1023
1024 function nitropack_get_conflicting_plugins() {
1025 $clashingPlugins = array();
1026
1027 if (defined('BREEZE_PLUGIN_DIR')) { // Breeze cache plugin
1028 $clashingPlugins[] = "Breeze";
1029 }
1030
1031 if (defined('WP_ROCKET_VERSION')) { // WP-Rocket
1032 $clashingPlugins[] = "WP-Rocket";
1033 }
1034
1035 if (defined('W3TC')) { // W3 Total Cache
1036 $clashingPlugins[] = "W3 Total Cache";
1037 }
1038
1039 if (defined('WPFC_MAIN_PATH')) { // WP Fastest Cache
1040 $clashingPlugins[] = "WP Fastest Cache";
1041 }
1042
1043 if (defined('PHASTPRESS_VERSION')) { // PhastPress
1044 $clashingPlugins[] = "PhastPress";
1045 }
1046
1047 if (defined('WPCACHEHOME') && function_exists("wp_cache_phase2")) { // WP Super Cache
1048 $clashingPlugins[] = "WP Super Cache";
1049 }
1050
1051 if (defined('LSCACHE_ADV_CACHE') || defined('LSCWP_DIR')) { // LiteSpeed Cache
1052 $clashingPlugins[] = "LiteSpeed Cache";
1053 }
1054
1055 if (class_exists('Swift_Performance') || class_exists('Swift_Performance_Lite')) { // Swift Performance
1056 $clashingPlugins[] = "Swift Performance";
1057 }
1058
1059 if (class_exists('PagespeedNinja')) { // PageSpeed Ninja
1060 $clashingPlugins[] = "PageSpeed Ninja";
1061 }
1062
1063 if (defined('AUTOPTIMIZE_PLUGIN_VERSION')) { // Autoptimize
1064 $clashingPlugins[] = "Autoptimize";
1065 }
1066
1067 if (defined('PEGASAAS_ACCELERATOR_VERSION')) { // Pegasaas Accelerator WP
1068 $clashingPlugins[] = "Pegasaas Accelerator WP";
1069 }
1070
1071 if (defined('WPHB_VERSION')) { // Hummingbird
1072 $clashingPlugins[] = "Hummingbird";
1073 }
1074
1075 if (defined('WP_SMUSH_VERSION')) { // Smush by WPMU DEV
1076 if (class_exists('Smush\\Core\\Settings') && defined('WP_SMUSH_PREFIX')) {
1077 $smushLazy = Smush\Core\Settings::get_instance()->get( 'lazy_load' );
1078 if ($smushLazy) {
1079 $clashingPlugins[] = "Smush Lazy Load";
1080 }
1081 } else {
1082 $clashingPlugins[] = "Smush";
1083 }
1084 }
1085
1086 if (defined('COMET_CACHE_PLUGIN_FILE')) { // Comet Cache by WP Sharks
1087 $clashingPlugins[] = "Comet Cache";
1088 }
1089
1090 if (defined('WPO_VERSION') && class_exists('WPO_Cache_Config')) { // WP Optimize
1091 $wpo_cache_config = WPO_Cache_Config::instance();
1092 if ($wpo_cache_config->get_option('enable_page_caching', false)) {
1093 $clashingPlugins[] = "WP Optimize page caching";
1094 }
1095 }
1096
1097 if (class_exists('BJLL')) { // BJ Lazy Load
1098 $clashingPlugins[] = "BJ Lazy Load";
1099 }
1100
1101 if (defined('SHORTPIXEL_IMAGE_OPTIMISER_VERSION') && class_exists('\ShortPixel\ShortPixelPlugin')) { //ShortPixel WebP
1102 $sp_config = \ShortPixel\ShortPixelPlugin::getInstance();
1103 if ($sp_config->settings()->createWebp) {
1104 $clashingPlugins[] = "ShortPixel WebP image creation";
1105 }
1106 }
1107
1108 return $clashingPlugins;
1109 }
1110
1111 function nitropack_is_conflicting_plugin_active() {
1112 $conflictingPlugins = nitropack_get_conflicting_plugins();
1113 return !empty($conflictingPlugins);
1114 }
1115
1116 function nitropack_is_advanced_cache_allowed() {
1117 return !in_array(nitropack_detect_hosting(), array(
1118 "pressable"
1119 ));
1120 }
1121
1122 function nitropack_admin_notices() {
1123 if (!empty($_COOKIE["nitropack_after_activate_notice"])) {
1124 nitropack_print_notice("info", "<script>document.cookie = 'nitropack_after_activate_notice=1; expires=Thu, 01 Jan 1970 00:00:01 GMT;';</script>NitroPack has been successfully activated, but it is not connected yet. Please go to <a href='" . admin_url( 'options-general.php?page=nitropack' ) . "'>its settings</a> page to connect it in order to start optimizing your site!");
1125 }
1126
1127 $screen = get_current_screen();
1128 if ($screen->id != 'settings_page_nitropack') {
1129 foreach (get_nitropack()->Notifications->get('system') as $notification) {
1130 nitropack_print_notice('info', $notification['message'], $notification["id"]);
1131 }
1132 }
1133
1134 nitropack_print_hosting_notice();
1135 nitropack_print_woocommerce_notice();
1136 }
1137
1138 function nitropack_get_hosting_notice_file() {
1139 return nitropack_trailingslashit(NITROPACK_DATA_DIR) . "hosting_notice";
1140 }
1141
1142 function nitropack_print_hosting_notice() {
1143 $hostingNoticeFile = nitropack_get_hosting_notice_file();
1144 if (!get_nitropack()->isConnected() || file_exists($hostingNoticeFile)) return;
1145
1146 $documentedHostingSetups = array(
1147 "flywheel" => array(
1148 "name" => "Flywheel",
1149 "helpUrl" => "https://getflywheel.com/wordpress-support/how-to-enable-wp_cache/"
1150 ),
1151 "cloudways" => array(
1152 "name" => "Cloudways",
1153 "helpUrl" => "https://support.nitropack.io/hc/en-us/articles/360060916674-Cloudways-Hosting-Configuration-for-NitroPack"
1154 )
1155 );
1156
1157 $siteConfig = nitropack_get_site_config();
1158 if ($siteConfig && !empty($siteConfig["hosting"]) && array_key_exists($siteConfig["hosting"], $documentedHostingSetups)) {
1159 $hostingInfo = $documentedHostingSetups[$siteConfig["hosting"]];
1160 $showNotice = true;
1161 if ($siteConfig["hosting"] == "flywheel" && defined("WP_CACHE") && WP_CACHE) $showNotice = false;
1162
1163 if ($showNotice) {
1164 nitropack_print_notice("info", sprintf("It looks like you are hosted on %s. Please follow <a href='%s' target='_blank'>these instructions</a> in order to make sure that everything works correctly. <a href='javascript:void(0);' onclick='jQuery.post(ajaxurl, {action: \"nitropack_dismiss_hosting_notice\"});jQuery(this).closest(\".is-dismissible\").hide();'>Dismiss</a>", $hostingInfo["name"], $hostingInfo["helpUrl"]));
1165 }
1166 }
1167 }
1168
1169 function nitropack_dismiss_hosting_notice() {
1170 $hostingNoticeFile = nitropack_get_hosting_notice_file();
1171 if (WP_DEBUG) {
1172 touch($hostingNoticeFile);
1173 } else {
1174 @touch($hostingNoticeFile);
1175 }
1176 }
1177
1178 function nitropack_print_woocommerce_notice() {
1179 if (get_nitropack()->isConnected()) {
1180 if (class_exists('WooCommerce')) {
1181 $wcOneTimeNotice = get_option('nitropack-wcNotice');
1182 if ($wcOneTimeNotice === false) {
1183 nitropack_print_notice("success", "WooCommerce is detected. Your <strong>Account</strong>, <strong>cart</strong> and <strong>checkout</strong> pages are automatically excluded from optimization. <a href='javascript:void(0);' onclick='jQuery.post(ajaxurl, {action: \"nitropack_dismiss_woocommerce_notice\"});jQuery(this).closest(\".is-dismissible\").hide();'>Dismiss</a>");
1184 }
1185 }
1186 }
1187 }
1188
1189 function nitropack_dismiss_woocommerce_notice() {
1190 update_option('nitropack-wcNotice', 1);
1191 }
1192
1193 function nitropack_is_config_up_to_date() {
1194 $siteConfig = nitropack_get_site_config();
1195 return !empty($siteConfig) && !empty($siteConfig["pluginVersion"]) && $siteConfig["pluginVersion"] == NITROPACK_VERSION;
1196 }
1197
1198 function nitropack_filter_non_original_cookies(&$cookies) {
1199 global $np_originalRequestCookies;
1200 $ogNames = is_array($np_originalRequestCookies) ? array_keys($np_originalRequestCookies) : array();
1201 foreach ($cookies as $name=>$val) {
1202 if (!in_array($name, $ogNames)) {
1203 unset($cookies[$name]);
1204 }
1205 }
1206 }
1207
1208 function nitropack_add_meta_box() {
1209 if ( current_user_can( 'manage_options' ) || current_user_can( 'nitropack_meta_box' ) ) {
1210 foreach (nitropack_get_cacheable_object_types() as $objectType) {
1211 add_meta_box( 'nitropack_manage_cache_box', 'NitroPack', 'nitropack_print_meta_box', $objectType, 'side' );
1212 }
1213 }
1214 }
1215
1216 // This is only used for post types that can have "single" pages
1217 function nitropack_print_meta_box($post) {
1218 wp_enqueue_script('nitropack_metabox_js', plugin_dir_url(__FILE__) . 'view/javascript/metabox.js?np_v=' . NITROPACK_VERSION, true);
1219 $html = '';
1220 $html .= '<p><a class="button nitropack-invalidate-single" data-post_id="' . $post->ID . '" data-post_url="' . get_permalink($post) . '" style="width:100%;text-align:center;padding: 3px 0;">Invalidate cache</a></p>';
1221 $html .= '<p><a class="button nitropack-purge-single" data-post_id="' . $post->ID . '" data-post_url="' . get_permalink($post) . '" style="width:100%;text-align:center;padding: 3px 0;">Purge cache</a></p>';
1222 $html .= '<p id="nitropack-status-msg" style="display:none;"></p>';
1223 echo $html;
1224 }
1225
1226 function get_nitropack_sdk($siteId = null, $siteSecret = null, $urlOverride = NULL, $forwardExceptions = false) {
1227 return get_nitropack()->getSdk($siteId, $siteSecret, $urlOverride, $forwardExceptions);
1228 }
1229
1230 function get_nitropack_integration_url($integration, $nitro = null) {
1231 if ($nitro || (null !== $nitro = get_nitropack_sdk()) ) {
1232 return $nitro->integrationUrl($integration);
1233 }
1234
1235 return "#";
1236 }
1237
1238 function register_nitropack_settings() {
1239 register_setting( NITROPACK_OPTION_GROUP, 'nitropack-enableCompression', array('default' => -1) );
1240 }
1241
1242 function nitropack_get_layout() {
1243 $layout = "default";
1244
1245 if (nitropack_is_home()) {
1246 $layout = "home";
1247 } else if (is_page()) {
1248 $layout = "page";
1249 } else if (is_attachment()) {
1250 $layout = "attachment";
1251 } else if (is_author()) {
1252 $layout = "author";
1253 } else if (is_search()) {
1254 $layout = "search";
1255 } else if (is_tag()) {
1256 $layout = "tag";
1257 } else if (is_tax()) {
1258 $layout = "taxonomy";
1259 } else if (is_category()) {
1260 $layout = "category";
1261 } else if (nitropack_is_archive()) {
1262 $layout = "archive";
1263 } else if (is_feed()) {
1264 $layout = "feed";
1265 } else if (is_page()) {
1266 $layout = "page";
1267 } else if (is_single()) {
1268 $layout = get_post_type();
1269 }
1270
1271 return $layout;
1272 }
1273
1274 function nitropack_sdk_invalidate($url = NULL, $tag = NULL, $reason = NULL) {
1275 if (null !== $nitro = get_nitropack_sdk()) {
1276 try {
1277 $siteConfig = nitropack_get_site_config();
1278 $homeUrl = $siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url();
1279
1280 if ($tag) {
1281 if (is_array($tag)) {
1282 $tag = array_map('nitropack_filter_tag', $tag);
1283 } else {
1284 $tag = nitropack_filter_tag($tag);
1285 }
1286 }
1287
1288 $nitro->invalidateCache($url, $tag, $reason);
1289
1290 try {
1291
1292 if (defined('NITROPACK_DEBUG_MODE')) {
1293 do_action('nitropack_debug_invalidate', $url, $tag, $reason);
1294 }
1295
1296 do_action('nitropack_integration_purge_url', $homeUrl);
1297
1298 if ($tag) {
1299 do_action('nitropack_integration_purge_all');
1300 } else if ($url) {
1301 do_action('nitropack_integration_purge_url', $url);
1302 } else {
1303 do_action('nitropack_integration_purge_all');
1304 }
1305 } catch (\Exception $e) {
1306 // Exception while signaling 3rd party integration addons to purge their cache
1307 }
1308 } catch (\Exception $e) {
1309 return false;
1310 }
1311
1312 return true;
1313 }
1314
1315 return false;
1316 }
1317
1318 /* Start Heartbeat Related Functions */
1319 function nitropack_is_heartbeat_needed() {
1320 return !nitropack_is_optimizer_request() &&
1321 !nitropack_is_amp_page() &&
1322 !nitropack_is_heartbeat_running() &&
1323 (!nitropack_is_heartbeat_completed() || time() - nitropack_last_heartbeat() > NITROPACK_HEARTBEAT_INTERVAL);
1324 }
1325
1326 function nitropack_print_heartbeat_script() {
1327 if (nitropack_is_heartbeat_needed()) {
1328 if (defined("NITROPACK_HEARTBEAT_PRINTED")) return;
1329 define("NITROPACK_HEARTBEAT_PRINTED", true);
1330 echo apply_filters("nitro_script_output", nitropack_get_heartbeat_script());
1331 }
1332 }
1333
1334 function nitropack_get_heartbeat_script() {
1335 $siteConfig = nitropack_get_site_config();
1336 if ($siteConfig && !empty($siteConfig["siteId"]) && !empty($siteConfig["siteSecret"])) {
1337 if (null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
1338 if (is_admin()) {
1339 $credentials = "same-origin";
1340 } else {
1341 $credentials = "omit";
1342 }
1343
1344 return "
1345 <script nitro-exclude>
1346 var heartbeatData = new FormData(); heartbeatData.append('nitroHeartbeat', '1');
1347 fetch(location.href, {method: 'POST', body: heartbeatData, credentials: '$credentials'});
1348 </script>";
1349 }
1350 }
1351 }
1352
1353 function is_valid_nitropack_heartbeat() {
1354 return !empty($_POST['nitroHeartbeat']);
1355 }
1356
1357 function nitropack_get_heartbeat_file() {
1358 if (null !== $nitro = get_nitropack_sdk()) {
1359 return nitropack_trailingslashit($nitro->getCacheDir()) . "heartbeat";
1360 } else {
1361 return nitropack_trailingslashit(NITROPACK_DATA_DIR) . "heartbeat";
1362 }
1363 }
1364
1365 function nitropack_last_heartbeat() {
1366 if (null !== $nitro = get_nitropack_sdk()) {
1367 try {
1368 return \NitroPack\SDK\Filesystem::fileMTime(nitropack_get_heartbeat_file());
1369 } catch (\Exception $e) {
1370 return 0;
1371 }
1372 }
1373 }
1374
1375 function nitropack_is_heartbeat_running() {
1376 if (null !== $nitro = get_nitropack_sdk()) {
1377 try {
1378 $heartbeatContent = \NitroPack\SDK\Filesystem::fileGetContents(nitropack_get_heartbeat_file());
1379 if ($heartbeatContent == "1") {
1380 return time() - nitropack_last_heartbeat() < NITROPACK_HEARTBEAT_INTERVAL;
1381 }
1382 } catch (\Exception $e) {
1383 return false;
1384 }
1385 }
1386 }
1387
1388 function nitropack_is_heartbeat_completed() {
1389 if (null !== $nitro = get_nitropack_sdk()) {
1390 try {
1391 $heartbeatContent = \NitroPack\SDK\Filesystem::fileGetContents(nitropack_get_heartbeat_file());
1392 return $heartbeatContent == "0"; // 0 - Job Done, 1 - Job Running, 2 - Job Needs Repeat
1393 } catch (\Exception $e) {
1394 return true;
1395 }
1396 }
1397 }
1398
1399 function nitropack_handle_heartbeat() {
1400 // TODO: Lock the file before checking this
1401 if (nitropack_is_heartbeat_running()) return;
1402
1403 session_write_close();
1404 if (null !== $nitro = get_nitropack_sdk()) {
1405 try {
1406 $success = true;
1407 \NitroPack\SDK\Filesystem::filePutContents(nitropack_get_heartbeat_file(), 1);
1408 if (nitropack_healthcheck()) {
1409 $success &= nitropack_flush_backlog();
1410 }
1411 $success &= nitropack_cache_cleanup();
1412
1413 if ($success) {
1414 \NitroPack\SDK\Filesystem::filePutContents(nitropack_get_heartbeat_file(), 0);
1415 } else {
1416 \NitroPack\SDK\Filesystem::filePutContents(nitropack_get_heartbeat_file(), 2);
1417 }
1418 } catch (\Exception $e) {
1419 return false;
1420 }
1421 }
1422 exit;
1423 }
1424
1425 function nitropack_healthcheck() {
1426 if (null !== $nitro = get_nitropack_sdk()) {
1427 return $nitro->getHealthStatus() == \NitroPack\SDK\HealthStatus::HEALTHY || $nitro->checkHealthStatus() == \NitroPack\SDK\HealthStatus::HEALTHY;
1428 }
1429 return true;
1430 }
1431
1432 function nitropack_flush_backlog() {
1433 if (null !== $nitro = get_nitropack_sdk()) {
1434 try {
1435 if ($nitro->backlog->exists()) {
1436 return $nitro->backlog->replay(30);
1437 }
1438 } catch (\NitroPack\SDK\BacklogReplayTimeoutException $e) {
1439 $nitro->backlog->delete();
1440 return nitropack_sdk_purge(NULL, NULL, "Full purge after backlog timeout");
1441 } catch (\Exception $e) {
1442 return false;
1443 }
1444 }
1445 return true;
1446 }
1447
1448 function nitropack_cache_cleanup() {
1449 if (null !== $nitro = get_nitropack_sdk()) {
1450 $cacheDirParent = dirname($nitro->getCacheDir());
1451 $entries = scandir($cacheDirParent);
1452 foreach ($entries as $entry) {
1453 if (strpos($entry, ".stale.") !== false) {
1454 $cacheDir = nitropack_trailingslashit($cacheDirParent) . $entry;
1455 try {
1456 \NitroPack\SDK\Filesystem::deleteDir($cacheDir);
1457 } catch (\Exception $e) {
1458 // TODO: Log this
1459 return false;
1460 }
1461 }
1462 }
1463 }
1464 return true;
1465 }
1466 /* End Heartbeat Related Functions */
1467
1468 function nitropack_sdk_purge($url = NULL, $tag = NULL, $reason = NULL, $type = \NitroPack\SDK\PurgeType::COMPLETE) {
1469 if (null !== $nitro = get_nitropack_sdk()) {
1470 try {
1471 $siteConfig = nitropack_get_site_config();
1472 $homeUrl = $siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url();
1473
1474 if ($tag) {
1475 if (is_array($tag)) {
1476 $tag = array_map('nitropack_filter_tag', $tag);
1477 } else {
1478 $tag = nitropack_filter_tag($tag);
1479 }
1480 }
1481
1482 if (!$url && !$tag) {
1483 $nitro->purgeLocalCache(true);
1484 }
1485
1486 $nitro->purgeCache($url, $tag, $type, $reason);
1487
1488 if (defined('NITROPACK_DEBUG_MODE')) {
1489 do_action('nitropack_debug_purge', $url, $tag, $reason);
1490 }
1491
1492 try {
1493 do_action('nitropack_integration_purge_url', $homeUrl);
1494
1495 if ($tag) {
1496 do_action('nitropack_integration_purge_all');
1497 } else if ($url) {
1498 do_action('nitropack_integration_purge_url', $url);
1499 } else {
1500 do_action('nitropack_integration_purge_all');
1501 }
1502 } catch (\Exception $e) {
1503 // Exception while signaling 3rd party integration addons to purge their cache
1504 }
1505 } catch (\Exception $e) {
1506 return false;
1507 }
1508
1509 return true;
1510 }
1511
1512 return false;
1513 }
1514
1515 function nitropack_sdk_purge_local($url = NULL) {
1516 if (null !== $nitro = get_nitropack_sdk()) {
1517 try {
1518 if ($url) {
1519 $nitro->purgeLocalUrlCache($url);
1520 do_action('nitropack_integration_purge_url', $url);
1521 } else {
1522 $nitro->purgeLocalCache(true);
1523
1524 try {
1525 do_action('nitropack_integration_purge_all');
1526 } catch (\Exception $e) {
1527 // Exception while signaling our 3rd party integration addons to purge their cache
1528 }
1529 }
1530 } catch (\Exception $e) {
1531 return false;
1532 }
1533
1534 return true;
1535 }
1536
1537 return false;
1538 }
1539
1540 function nitropack_sdk_delete_backlog() {
1541 if (null !== $nitro = get_nitropack_sdk()) {
1542 try {
1543 if ($nitro->backlog->exists()) {
1544 $nitro->backlog->delete();
1545 }
1546 } catch (\Exception $e) {
1547 return false;
1548 }
1549
1550 return true;
1551 }
1552
1553 return false;
1554 }
1555
1556 function nitropack_purge($url = NULL, $tag = NULL, $reason = NULL) {
1557 if ($tag != "pageType:home") {
1558 $siteConfig = nitropack_get_site_config();
1559 $homeUrl = $siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url();
1560 nitropack_log_invalidate($homeUrl, "pageType:home", $reason);
1561 }
1562
1563 if ($tag != "pageType:archive") {
1564 nitropack_log_invalidate(NULL, "pageType:archive", $reason);
1565 }
1566
1567 nitropack_log_purge($url, $tag, $reason);
1568 }
1569
1570 function nitropack_log_purge($url = NULL, $tag = NULL, $reason = NULL) {
1571 global $np_loggedPurges;
1572 if ($tag && is_array($tag)) {
1573 foreach ($tag as $tagSingle) {
1574 nitropack_log_purge($url, $tagSingle, $reason);
1575 }
1576 return;
1577 }
1578
1579 $keyBase = "";
1580 if ($url) {
1581 $keyBase .= $url;
1582 }
1583
1584 if ($tag) {
1585 $tag = nitropack_filter_tag($tag);
1586 $keyBase .= $tag;
1587 }
1588
1589 $purgeRequestKey = md5($keyBase);
1590 if (is_array($np_loggedPurges) && array_key_exists($purgeRequestKey, $np_loggedPurges)) {
1591 $np_loggedPurges[$purgeRequestKey]["reason"] = $reason;
1592 $np_loggedPurges[$purgeRequestKey]["priority"]++;
1593 } else {
1594 $np_loggedPurges[$purgeRequestKey] = array(
1595 "url" => $url,
1596 "tag" => $tag,
1597 "reason" => $reason,
1598 "priority" => 1
1599 );
1600 }
1601 }
1602
1603 function nitropack_invalidate($url = NULL, $tag = NULL, $reason = NULL) {
1604 if ($tag != "pageType:home") {
1605 $siteConfig = nitropack_get_site_config();
1606 $homeUrl = $siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url();
1607 nitropack_log_invalidate($homeUrl, "pageType:home", $reason);
1608 }
1609
1610 if ($tag != "pageType:archive") {
1611 nitropack_log_invalidate(NULL, "pageType:archive", $reason);
1612 }
1613
1614 nitropack_log_invalidate($url, $tag, $reason);
1615 }
1616
1617 function nitropack_log_invalidate($url = NULL, $tag = NULL, $reason = NULL) {
1618 global $np_loggedInvalidations;
1619 if ($tag && is_array($tag)) {
1620 foreach ($tag as $tagSingle) {
1621 nitropack_log_invalidate($url, $tagSingle, $reason);
1622 }
1623 return;
1624 }
1625
1626 $keyBase = "";
1627 if ($url) {
1628 $keyBase .= $url;
1629 }
1630
1631 if ($tag) {
1632 $tag = nitropack_filter_tag($tag);
1633 $keyBase .= $tag;
1634 }
1635
1636 $invalidateRequestKey = md5($keyBase);
1637 if (is_array($np_loggedInvalidations) && array_key_exists($invalidateRequestKey, $np_loggedInvalidations)) {
1638 $np_loggedInvalidations[$invalidateRequestKey]["reason"] = $reason;
1639 $np_loggedInvalidations[$invalidateRequestKey]["priority"]++;
1640 } else {
1641 $np_loggedInvalidations[$invalidateRequestKey] = array(
1642 "url" => $url,
1643 "tag" => $tag,
1644 "reason" => $reason,
1645 "priority" => 1
1646 );
1647 }
1648 }
1649
1650 function nitropack_queue_sort($a, $b) {
1651 if ($a["priority"] == $b["priority"]) {
1652 return 0;
1653 }
1654 return ($a["priority"] < $b["priority"]) ? -1 : 1;
1655 }
1656
1657 function nitropack_execute_purges() {
1658 global $np_loggedPurges;
1659 if (!empty($_GET["action"]) && ($_GET["action"] === "edit") && !empty($_GET["meta-box-loader"])) {
1660 return;
1661 }
1662 if (!empty($np_loggedPurges)) {
1663 uasort($np_loggedPurges, "nitropack_queue_sort");
1664 foreach ($np_loggedPurges as $requestKey => $data) {
1665 nitropack_sdk_purge($data["url"], $data["tag"], $data["reason"]);
1666 }
1667 }
1668 }
1669
1670 function nitropack_execute_invalidations() {
1671 global $np_loggedInvalidations;
1672 if (!empty($_GET["action"]) && ($_GET["action"] === "edit") && !empty($_GET["meta-box-loader"])) {
1673 return;
1674 }
1675 if (!empty($np_loggedInvalidations)) {
1676 uasort($np_loggedInvalidations, "nitropack_queue_sort");
1677 foreach ($np_loggedInvalidations as $requestKey => $data) {
1678 nitropack_sdk_invalidate($data["url"], $data["tag"], $data["reason"]);
1679 }
1680 }
1681 }
1682
1683 function nitropack_execute_warmups() {
1684 global $np_loggedWarmups;
1685 if (!empty($_GET["action"]) && ($_GET["action"] === "edit") && !empty($_GET["meta-box-loader"])) {
1686 return;
1687 }
1688 try {
1689 if (!empty($np_loggedWarmups) && (null !== $nitro = get_nitropack_sdk())) {
1690 $warmupStats = $nitro->getApi()->getWarmupStats();
1691 if (!empty($warmupStats["status"])) {
1692 foreach (array_unique($np_loggedWarmups) as $url) {
1693 $nitro->getApi()->runWarmup($url);
1694 }
1695 }
1696 }
1697 } catch (\Exception $e) {}
1698 }
1699
1700 function nitropack_fetch_config() {
1701 if (null !== $nitro = get_nitropack_sdk()) {
1702 try {
1703 $nitro->fetchConfig();
1704 } catch (\Exception $e) {}
1705 }
1706 }
1707
1708 function nitropack_theme_handler($event = NULL) {
1709 if (!get_option("nitropack-autoCachePurge", 1)) return;
1710
1711 $msg = $event ? $event : 'Theme switched';
1712
1713 try {
1714 nitropack_sdk_purge(NULL, NULL, $msg); // purge entire cache
1715 } catch (\Exception $e) {}
1716 }
1717
1718 function nitropack_purge_cache() {
1719 try {
1720 if (nitropack_sdk_purge(NULL, NULL, 'Manual purge of all pages')) {
1721 nitropack_json_and_exit(array(
1722 "type" => "success",
1723 "message" => __( 'Success! Cache has been purged successfully!', 'nitropack' )
1724 ));
1725 }
1726 } catch (\Exception $e) {}
1727
1728 nitropack_json_and_exit(array(
1729 "type" => "error",
1730 "message" => __( 'Error! There was an error and the cache was not purged!', 'nitropack' )
1731 ));
1732 }
1733
1734 function nitropack_invalidate_cache() {
1735 try {
1736 if (nitropack_sdk_invalidate(NULL, NULL, 'Manual invalidation of all pages')) {
1737 nitropack_json_and_exit(array(
1738 "type" => "success",
1739 "message" => __( 'Success! Cache has been invalidated successfully!', 'nitropack' )
1740 ));
1741 }
1742 } catch (\Exception $e) {}
1743
1744 nitropack_json_and_exit(array(
1745 "type" => "error",
1746 "message" => __( 'Error! There was an error and the cache was not invalidated!', 'nitropack' )
1747 ));
1748 }
1749
1750 function nitropack_clear_residual_cache() {
1751 $gde = !empty($_POST["gde"]) ? $_POST["gde"] : NULL;
1752 if ($gde && array_key_exists($gde, NitroPack\Integration\Plugin\RC::$modules)) {
1753 $result = call_user_func(array(NitroPack\Integration\Plugin\RC::$modules[$gde], "clearCache")); // This needs to be like this because of compatibility with PHP 5.6
1754 if (!in_array(false, $result)) {
1755 nitropack_json_and_exit(array(
1756 "type" => "success",
1757 "message" => __( 'Success! The residual cache has been cleared successfully!', 'nitropack' )
1758 ));
1759 }
1760 }
1761 nitropack_json_and_exit(array(
1762 "type" => "error",
1763 "message" => __( 'Error! There was an error clearing the residual cache!', 'nitropack' )
1764 ));
1765 }
1766
1767 function nitropack_json_and_exit($array) {
1768 if (nitropack_is_wp_cli()) {
1769 $type = NULL;
1770 if (array_key_exists("status", $array)) {
1771 $type = $array["status"];
1772 } else if (array_key_exists("type", $array)) {
1773 $type = $array["type"];
1774 }
1775
1776 if ($type && array_key_exists("message", $array)) {
1777 if ($type == "success") {
1778 WP_CLI::success($array["message"]);
1779 } else {
1780 WP_CLI::error($array["message"]);
1781 }
1782 }
1783 } else {
1784 echo json_encode($array);
1785 }
1786 exit;
1787 }
1788
1789 function nitropack_has_post_important_change($post) {
1790 $prevPost = nitropack_get_post_pre_update($post);
1791 return $prevPost && ($prevPost->post_title != $post->post_title || $prevPost->post_name != $post->post_name || $prevPost->post_excerpt != $post->post_excerpt);
1792 }
1793
1794 function nitropack_purge_single_cache() {
1795 if (!empty($_POST["postId"]) && is_numeric($_POST["postId"])) {
1796 $postId = $_POST["postId"];
1797 $postUrl = !empty($_POST["postUrl"]) ? $_POST["postUrl"] : NULL;
1798 $reason = sprintf("Manual purge of post %s via the WordPress admin panel", $postId);
1799 $tag = $postId > 0 ? "single:$postId" : NULL;
1800
1801 if ($postUrl) {
1802 if (is_array($postUrl)) {
1803 foreach ($postUrl as &$url) {
1804 $url = nitropack_sanitize_url_input($url);
1805 }
1806 } else {
1807 $postUrl = nitropack_sanitize_url_input($postUrl);
1808 $reason = "Manual purge of " . $postUrl;
1809 }
1810 }
1811
1812 try {
1813 if (nitropack_sdk_purge($postUrl, $tag, $reason)) {
1814 nitropack_json_and_exit(array(
1815 "type" => "success",
1816 "message" => __( 'Success! Cache has been purged successfully!', 'nitropack' )
1817 ));
1818 }
1819 } catch (\Exception $e) {}
1820 }
1821
1822 nitropack_json_and_exit(array(
1823 "type" => "error",
1824 "message" => __( 'Error! There was an error and the cache was not purged!', 'nitropack' )
1825 ));
1826 }
1827
1828 function nitropack_invalidate_single_cache() {
1829 if (!empty($_POST["postId"]) && is_numeric($_POST["postId"])) {
1830 $postId = $_POST["postId"];
1831 $postUrl = !empty($_POST["postUrl"]) ? $_POST["postUrl"] : NULL;
1832 $reason = sprintf("Manual invalidation of post %s via the WordPress admin panel", $postId);
1833 $tag = $postId > 0 ? "single:$postId" : NULL;
1834
1835 if ($postUrl) {
1836 if (is_array($postUrl)) {
1837 foreach ($postUrl as &$url) {
1838 $url = nitropack_sanitize_url_input($url);
1839 }
1840 } else {
1841 $postUrl = nitropack_sanitize_url_input($postUrl);
1842 $reason = "Manual invalidation of " . $postUrl;
1843 }
1844 }
1845
1846 try {
1847 if (nitropack_sdk_invalidate($postUrl, $tag, $reason)) {
1848 nitropack_json_and_exit(array(
1849 "type" => "success",
1850 "message" => __( 'Success! Cache has been invalidated successfully!', 'nitropack' )
1851 ));
1852 }
1853 } catch (\Exception $e) {}
1854 }
1855
1856 nitropack_json_and_exit(array(
1857 "type" => "error",
1858 "message" => __( 'Error! There was an error and the cache was not invalidated!', 'nitropack' )
1859 ));
1860 }
1861
1862 function nitropack_clean_post_cache($post, $taxonomies = NULL, $hasImportantChangeInPost = NULL, $reason = NULL, $usePurge = false) {
1863 try {
1864 $postID = $post->ID;
1865 $postType = isset($post->post_type) ? $post->post_type : "post";
1866 $nicePostTypeLabel = nitropack_get_nice_post_type_label($postType);
1867 $reason = $reason ? $reason : sprintf("Updated %s '%s'", $nicePostTypeLabel, $post->post_title);
1868 $cacheableObjectTypes = nitropack_get_cacheable_object_types();
1869
1870 if (in_array($postType, $cacheableObjectTypes)) {
1871 if ($usePurge) {
1872 // We only purge the single pages because they have to immediately stop serving cache
1873 // These pages no longer exists and if their URL is requested we must not server cache
1874 nitropack_purge(NULL, "single:$postID", $reason);
1875 } else {
1876 nitropack_invalidate(NULL, "single:$postID", $reason);
1877 }
1878
1879 nitropack_invalidate(NULL, "post:$postID", $reason);
1880
1881 if ($hasImportantChangeInPost === NULL) {
1882 $hasImportantChangeInPost = nitropack_has_post_important_change($post);
1883 }
1884 if ($taxonomies === NULL) {
1885 if ($hasImportantChangeInPost) { // This change should be reflected in all taxonomy pages
1886 $taxonomies = array('related' => nitropack_get_taxonomies($post));
1887 } else { // No important change, so only update taxonomy pages which have been added or removed from the post
1888 $taxonomies = nitropack_get_taxonomies_for_update($post);
1889 }
1890 }
1891 if ($taxonomies) {
1892 if (!empty($taxonomies['added'])) { // taxonomies that the post was just added to, must purge all pages for these taxonomies
1893 foreach ($taxonomies['added'] as $term_taxonomy_id) {
1894 nitropack_invalidate(NULL, "tax:$term_taxonomy_id", $reason);
1895 }
1896 }
1897 if (!empty($taxonomies['deleted'])) { // taxonomy pages that the post was just removed from (also accounts for paginations via the taxpost: tag instead of only tax:)
1898 foreach ($taxonomies['deleted'] as $term_taxonomy_id) {
1899 nitropack_invalidate(NULL, "taxpost:$term_taxonomy_id:$postID", $reason);
1900 }
1901 }
1902 if (!empty($taxonomies['related'])) { // taxonomy pages that the post is linked to (also accounts for paginations via the taxpost: tag instead of only tax:)
1903 foreach ($taxonomies['related'] as $term_taxonomy_id) {
1904 nitropack_invalidate(NULL, "taxpost:$term_taxonomy_id:$postID", $reason);
1905 }
1906 }
1907 }
1908 } else {
1909 if ($post->public) {
1910 nitropack_invalidate(NULL, "post:$postID", $reason);
1911 }
1912
1913 $posts = get_post_ancestors($postID);
1914 foreach ($posts as $parentID) {
1915 $parent = get_post($parentID);
1916 nitropack_clean_post_cache($parent, false, false, $reason);
1917 }
1918 }
1919 } catch (\Exception $e) {}
1920 }
1921
1922 function nitropack_get_nice_post_type_label($postType) {
1923 $postTypes = get_post_types(array(
1924 "name" => $postType
1925 ), "objects");
1926
1927 return !empty($postTypes[$postType]) && !empty($postTypes[$postType]->labels) ? $postTypes[$postType]->labels->singular_name : $postType;
1928 }
1929
1930 function nitropack_handle_comment_transition($new, $old, $comment) {
1931 if (!get_option("nitropack-autoCachePurge", 1)) return;
1932
1933 try {
1934 $postID = $comment->comment_post_ID;
1935 $post = get_post($postID);
1936 $postType = isset($post->post_type) ? $post->post_type : "post";
1937 $cacheableObjectTypes = nitropack_get_cacheable_object_types();
1938
1939 if (in_array($postType, $cacheableObjectTypes)) {
1940 nitropack_invalidate(NULL, "single:" . $postID, sprintf("Invalidation of '%s' due to changing related comment status", $post->post_title));
1941 }
1942 } catch (\Exception $e) {
1943 // TODO: Log the error
1944 }
1945 }
1946
1947 function nitropack_handle_comment_post($commentID, $isApproved) {
1948 if (!get_option("nitropack-autoCachePurge", 1) || $isApproved !== 1) return;
1949
1950 try {
1951 $comment = get_comment($commentID);
1952 $postID = $comment->comment_post_ID;
1953 $post = get_post($postID);
1954 nitropack_invalidate(NULL, "single:" . $postID, sprintf("Invalidation of '%s' due to posting a new approved comment", $post->post_title));
1955 } catch (\Exception $e) {
1956 // TODO: Log the error
1957 }
1958 }
1959
1960 function nitropack_handle_post_transition($new, $old, $post) {
1961 global $np_loggedWarmups;
1962 if (!empty($post->ID) && in_array($post->ID, \NitroPack\WordPress\NitroPack::$ignoreUpdatePostIDs)) return;
1963 if (!get_option("nitropack-autoCachePurge", 1)) return;
1964
1965 try {
1966 if ($new === "auto-draft" || ($new === "draft" && $old != "publish") || $new === "inherit") { // Creating a new post or draft, don't do anything for now.
1967 return;
1968 }
1969
1970 $ignoredPostTypes = array(
1971 "revision",
1972 "scheduled-action",
1973 "flamingo_contact",
1974 "carts"/*WooCommerce Cart Reports*/
1975 );
1976
1977 $nicePostTypes = array(
1978 "post" => "Post",
1979 "page" => "Page",
1980 "tribe_events" => "Calendar Event",
1981 );
1982 $postType = isset($post->post_type) ? $post->post_type : "post";
1983 $nicePostTypeLabel = nitropack_get_nice_post_type_label($postType);
1984
1985 if (in_array($postType, $ignoredPostTypes)) return;
1986
1987 switch ($postType) {
1988 case "nav_menu_item":
1989 nitropack_invalidate(NULL, NULL, sprintf("Invalidation of all pages due to modifying menu entries"));
1990 break;
1991 case "customize_changeset":
1992 nitropack_invalidate(NULL, NULL, sprintf("Invalidation of all pages due to applying appearance customization"));
1993 break;
1994 case "custom_css":
1995 nitropack_invalidate(NULL, NULL, sprintf("Invalidation of all pages due to modifying custom CSS"));
1996 break;
1997 default:
1998 if ($new == "future") {
1999 nitropack_clean_post_cache($post, array('added' => nitropack_get_taxonomies($post)), true, sprintf("Invalidate related pages due to scheduling %s '%s'", $nicePostTypeLabel, $post->post_title));
2000 } else if ($new == "publish" && $old != "publish") {
2001 nitropack_clean_post_cache($post, array('added' => nitropack_get_taxonomies($post)), true, sprintf("Invalidate related pages due to publishing %s '%s'", $nicePostTypeLabel, $post->post_title));
2002 $np_loggedWarmups[] = get_permalink($post);
2003 } else if ($new == "trash" && $old == "publish") {
2004 nitropack_clean_post_cache($post, array('deleted' => nitropack_get_taxonomies($post)), true, sprintf("Invalidate related pages due to deleting %s '%s'", $nicePostTypeLabel, $post->post_title), true);
2005 } else if ($new == "private" && $old == "publish") {
2006 nitropack_clean_post_cache($post, array('deleted' => nitropack_get_taxonomies($post)), true, sprintf("Invalidate related pages due to making %s '%s' private", $nicePostTypeLabel, $post->post_title), true);
2007 } else if ($new == "draft" && $old == "publish") {
2008 nitropack_clean_post_cache($post, array('deleted' => nitropack_get_taxonomies($post)), true, sprintf("Invalidate related pages due to making %s '%s' a draft", $nicePostTypeLabel, $post->post_title), true);
2009 } else if ($new != "trash") {
2010 nitropack_clean_post_cache($post);
2011 $np_loggedWarmups[] = get_permalink($post);
2012 }
2013 break;
2014 }
2015 } catch (\Exception $e) {
2016 // TODO: Log the error
2017 }
2018 }
2019
2020 function nitropack_handle_product_updates($product, $updated) {
2021 if (!get_option("nitropack-autoCachePurge", 1)) return;
2022
2023 try {
2024 $post = get_post($product->get_id());
2025 $reasons = 'updated ';
2026 $reasons .= implode(',', $updated);
2027 nitropack_clean_post_cache($post, NULL, true, sprintf("Invalidate product '%s'. Reason '%s'", $product->get_name(), $reasons)); // Update the product page and all related pages, because a quantity change might have to add/remove "Out of stock" labels
2028 } catch (\Exception $e) {
2029 // TODO: Log the error
2030 }
2031 }
2032
2033 function nitropack_post_link_listener($permalink, $post, $leavename) {
2034 if (is_object($post)) {
2035 nitropack_handle_the_post($post);
2036 }
2037
2038 return $permalink;
2039 }
2040
2041 function nitropack_handle_the_post($post) {
2042 global $np_customExpirationTimes, $np_queriedObj;
2043 if (defined('POSTEXPIRATOR_VERSION')) {
2044 $postExpiryDate = get_post_meta($post->ID, "_expiration-date", true);
2045 if (!empty($postExpiryDate) && $postExpiryDate > time()) { // We only need to look at future dates
2046 $np_customExpirationTimes[] = $postExpiryDate;
2047 }
2048 }
2049
2050 if (function_exists("sort_portfolio")) { // Portfolio Sorting plugin
2051 $portfolioStartDate = get_post_meta($post->ID, "start_date", true);
2052 $portfolioEndDate = get_post_meta($post->ID, "end_date", true);
2053 if (!empty($portfolioStartDate) && strtotime($portfolioStartDate) > time()) { // We only need to look at future dates
2054 $np_customExpirationTimes[] = strtotime($portfolioStartDate);
2055 } else if (!empty($portfolioEndDate) && strtotime($portfolioEndDate) > time()) { // We only need to look at future dates
2056 $np_customExpirationTimes[] = strtotime($portfolioEndDate);
2057 }
2058 }
2059
2060 $GLOBALS["NitroPack.tags"]["post:" . $post->ID] = 1;
2061 $GLOBALS["NitroPack.tags"]["author:" . $post->post_author] = 1;
2062 if ($np_queriedObj) {
2063 $GLOBALS["NitroPack.tags"]["taxpost:" . $np_queriedObj->term_taxonomy_id . ":" . $post->ID] = 1;
2064 }
2065 }
2066
2067 function nitropack_ignore_post_updates($postID) {
2068 \NitroPack\WordPress\NitroPack::$ignoreUpdatePostIDs[] = $postID;
2069 }
2070
2071 function nitropack_get_taxonomies($post) {
2072 $term_taxonomy_ids = array();
2073 $taxonomies = get_object_taxonomies($post->post_type);
2074 foreach ($taxonomies as $taxonomy) {
2075 $terms = get_the_terms( $post->ID, $taxonomy );
2076 if (!empty($terms)) {
2077 foreach ($terms as $term) {
2078 $term_taxonomy_ids[] = $term->term_taxonomy_id;
2079 }
2080 }
2081 }
2082 return $term_taxonomy_ids;
2083 }
2084
2085 function nitropack_get_taxonomies_for_update($post) {
2086 $prevTaxonomies = nitropack_get_taxonomies_pre_update($post);
2087 $newTaxonomies = nitropack_get_taxonomies($post);
2088 $intersection = array_intersect($newTaxonomies, $prevTaxonomies);
2089 $prevTaxonomies = array_diff($prevTaxonomies, $intersection);
2090 $newTaxonomies = array_diff($newTaxonomies, $intersection);
2091 return array(
2092 "added" => array_diff($newTaxonomies, $prevTaxonomies),
2093 "deleted" => array_diff($prevTaxonomies, $newTaxonomies)
2094 );
2095 }
2096
2097 function nitropack_get_post_pre_update($post) {
2098 return !empty(\NitroPack\WordPress\NitroPack::$preUpdatePosts[$post->ID]) ? \NitroPack\WordPress\NitroPack::$preUpdatePosts[$post->ID] : NULL;
2099 }
2100
2101 function nitropack_get_taxonomies_pre_update($post) {
2102 return !empty(\NitroPack\WordPress\NitroPack::$preUpdateTaxonomies[$post->ID]) ? \NitroPack\WordPress\NitroPack::$preUpdateTaxonomies[$post->ID] : array();
2103 }
2104
2105 function nitropack_log_post_pre_update($postID) {
2106 if (in_array($postID, \NitroPack\WordPress\NitroPack::$ignoreUpdatePostIDs)) return;
2107
2108 $post = get_post($postID);
2109 \NitroPack\WordPress\NitroPack::$preUpdatePosts[$postID] = $post;
2110 \NitroPack\WordPress\NitroPack::$preUpdateTaxonomies[$postID] = nitropack_get_taxonomies($post);
2111 }
2112
2113 function nitropack_filter_tag($tag) {
2114 return preg_replace("/[^a-zA-Z0-9:]/", ":", $tag);
2115 }
2116
2117 function nitropack_log_tags() {
2118 if (!empty($GLOBALS["NitroPack.instance"]) && !empty($GLOBALS["NitroPack.tags"])) {
2119 $nitro = $GLOBALS["NitroPack.instance"];
2120 $layout = nitropack_get_layout();
2121 try {
2122 if ($layout == "home") {
2123 $nitro->getApi()->tagUrl($nitro->getUrl(), "pageType:home");
2124 } else if ($layout == "archive") {
2125 $nitro->getApi()->tagUrl($nitro->getUrl(), "pageType:archive");
2126 } else {
2127 $nitro->getApi()->tagUrl($nitro->getUrl(), array_map("nitropack_filter_tag", array_keys($GLOBALS["NitroPack.tags"])));
2128 }
2129 } catch (\Exception $e) {}
2130 }
2131 }
2132
2133 function nitropack_extend_nonce_life($life) {
2134 // Nonce life should be extended only:
2135 // - if NitroPack is connected for this site
2136 // - if the current value is shorter than the life time of a cache file
2137 // - if no user is logged in
2138 // - for cacheable requests
2139 //
2140 // Reasons why we might need to extend the nonce life time even for requests that are not cacheable:
2141 // - a request may be cachable at first, but become uncachable during changes at runtime or user actions on the page (example: log in via AJAX on a category page. Once logged in the page will not redirect, but if there is an infinite scroll it will stop working if we stop extending the nonce life time)
2142 // - a request may seem cachable at first, but be determined uncachable during runtime (example: visit to a URL of a page whose post type does not match the enabled cacheable post types, or a cart, checkout page, etc.)
2143
2144 if ((null !== $nitro = get_nitropack_sdk())) {
2145 $siteConfig = nitropack_get_site_config();
2146 if ($siteConfig && !empty($siteConfig["isDlmActive"]) && !empty($siteConfig["dlm_downloading_url"]) && !empty($siteConfig["dlm_download_endpoint"])) {
2147 $currentUrl = $nitro->getUrl();
2148 if (strpos($currentUrl, $siteConfig["dlm_downloading_url"]) !== false || strpos($currentUrl, $siteConfig["dlm_download_endpoint"]) !== false) {
2149 // Do not modify the nonce times on pages of Download Monitor
2150 return $life;
2151 }
2152 }
2153 $cacheExpiration = $nitro->getConfig()->PageCache->ExpireTime;
2154 return $cacheExpiration > $life ? $cacheExpiration : $life; // Extend the life of cacheable nonces up to the cache expiration time if needed
2155 }
2156 return $life;
2157 }
2158
2159 function nitropack_reconfigure_webhooks() {
2160 $siteConfig = nitropack_get_site_config();
2161
2162 if ($siteConfig && !empty($siteConfig["siteId"])) {
2163 $siteId = $siteConfig["siteId"];
2164 if (null !== $nitro = get_nitropack_sdk()) {
2165 $token = nitropack_generate_webhook_token($siteId);
2166 try {
2167 nitropack_setup_webhooks($nitro, $token);
2168 update_option("nitropack-webhookToken", $token);
2169 nitropack_json_and_exit(array("status" => "success"));
2170 } catch (\NitroPack\SDK\WebhookException $e) {
2171 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Webhook Error: ', 'nitropack' ) . $e->getMessage()));
2172 }
2173 } else {
2174 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Unable to get SDK instance', 'nitropack' )));
2175 }
2176 } else {
2177 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Incomplete site config. Please reinstall the plugin!', 'nitropack' )));
2178 }
2179 }
2180
2181 function nitropack_generate_webhook_token($siteId) {
2182 return md5(__FILE__ . ":" . $siteId);
2183 }
2184
2185 function nitropack_verify_connect_ajax() {
2186 $siteId = !empty($_POST["siteId"]) ? $_POST["siteId"] : "";
2187 $siteSecret = !empty($_POST["siteSecret"]) ? $_POST["siteSecret"] : "";
2188 nitropack_verify_connect($siteId, $siteSecret);
2189 }
2190
2191 function nitropack_check_func_availability($func_name) {
2192 if (function_exists('ini_get')) {
2193 $existsResult = stripos(ini_get('disable_functions'), $func_name) === false;
2194 } else {
2195 $existsResult = function_exists($func_name);
2196 }
2197 return $existsResult;
2198 }
2199
2200 function nitropack_prevent_connecting($nitroSDK) {
2201 $remoteUrl = $nitroSDK->getApi()->getWebhook("config");
2202 if (empty($remoteUrl)) {
2203 return false;
2204 }
2205 $siteConfig = nitropack_get_site_config();
2206 $localUrl = new \NitroPack\Url\Url($siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url());
2207 $localHome = strtolower($localUrl->getHost() . $localUrl->getPath());
2208 $storedUrl = new \NitroPack\Url\Url($remoteUrl);
2209 $remoteHome = strtolower($storedUrl->getHost() . $storedUrl->getPath());
2210 if ($localHome === $remoteHome) {
2211 return false;
2212 }
2213 return array('local' => $localHome, 'remote' => $remoteHome);
2214 }
2215
2216 function nitropack_verify_connect($siteId, $siteSecret) {
2217 if (!nitropack_check_func_availability('stream_socket_client')) {
2218 nitropack_json_and_exit(array("status" => "error", "message" => "stream_socket_client function is not allowed by your host. <a href=\"https://support.nitropack.io/hc/en-us/articles/360020898137\" target=\"_blank\" rel=\"noreferrer noopener\">Read more</a>"));
2219 }
2220
2221 if (empty($siteId) || empty($siteSecret)) {
2222 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Site ID and Site Secret cannot be empty', 'nitropack' )));
2223 }
2224
2225 //remove tags and whitespaces
2226 $siteId = trim(esc_attr($siteId));
2227 $siteSecret = trim(esc_attr($siteSecret));
2228
2229 if (!nitropack_validate_site_id($siteId) || !nitropack_validate_site_secret($siteSecret)) {
2230 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Invalid Site ID or Site Secret value', 'nitropack' )));
2231 }
2232
2233 try {
2234 $blogId = get_current_blog_id();
2235 if (null !== $nitro = get_nitropack_sdk($siteId, $siteSecret, NULL, true)) {
2236 if (!$nitro->checkHealthStatus()) {
2237 nitropack_json_and_exit(array(
2238 "status" => "error",
2239 "message" => __( 'Error when trying to communicate with NitroPack\'s servers. Please try again in a few minutes. If the issue persists, please', 'nitropack' )." <a href='https://support.nitropack.io/hc/en-us' target='_blank'>contact us</a>."
2240 ));
2241 }
2242
2243 $preventParing = apply_filters('nitropack_prevent_connect', nitropack_prevent_connecting($nitro));
2244 if ($preventParing) {
2245 nitropack_json_and_exit(array(
2246 "status" => "error",
2247 "message" => "It looks like another site <strong>({$preventParing['remote']})</strong> is already connected using these credentials. Either disconnect it or register a new site in your NitroPack dashboard.<br/>
2248 <a href='https://support.nitropack.io/hc/en-us/articles/4405254569745' target='_blank' rel='noreferrer noopener'>Read more</a>"
2249 ));
2250 }
2251 $token = nitropack_generate_webhook_token($siteId);
2252 update_option("nitropack-webhookToken", $token);
2253 update_option("nitropack-enableCompression", -1);
2254 update_option("nitropack-autoCachePurge", get_option("nitropack-autoCachePurge", 1));
2255 update_option("nitropack-cacheableObjectTypes", nitropack_get_default_cacheable_object_types());
2256
2257 nitropack_setup_webhooks($nitro, $token);
2258
2259 // _icl_current_language is WPML cookie, it is added here for compatibility with this module
2260 $customVariationCookies = array("np_wc_currency", "np_wc_currency_language", "_icl_current_language");
2261 $variationCookies = $nitro->getApi()->getVariationCookies();
2262 foreach ($variationCookies as $cookie) {
2263 $index = array_search($cookie["name"], $customVariationCookies);
2264 if ($index !== false) {
2265 array_splice($customVariationCookies, $index, 1);
2266 }
2267 }
2268
2269 foreach ($customVariationCookies as $cookieName) {
2270 $nitro->getApi()->setVariationCookie($cookieName);
2271 }
2272
2273 $nitro->fetchConfig(); // Reload the variation cookies
2274
2275 get_nitropack()->updateCurrentBlogConfig($siteId, $siteSecret, $blogId);
2276 nitropack_install_advanced_cache();
2277
2278 try {
2279 do_action('nitropack_integration_purge_all');
2280 } catch (\Exception $e) {
2281 // Exception while signaling our 3rd party integration addons to purge their cache
2282 }
2283
2284 nitropack_event("connect", $nitro);
2285 nitropack_event("enable_extension", $nitro);
2286
2287 // Optimize front page
2288 $siteConfig = nitropack_get_site_config();
2289 if ($siteConfig) {
2290 $nitro->getApi()->runWarmup([$siteConfig['home_url']], true); // force run a warmup on the home page
2291 }
2292
2293 nitropack_json_and_exit(array("status" => "success"));
2294 }
2295 } catch (\NitroPack\SDK\WebhookException $e) {
2296 nitropack_json_and_exit(array("status" => "error", "message" => $e->getMessage()));
2297 } catch (\NitroPack\SDK\StorageException $e) {
2298 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Permission Error: ', 'nitropack' ) . $e->getMessage()));
2299 } catch (\NitroPack\SDK\EmptyConfigException $e) {
2300 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Error while fetching remote config: ', 'nitropack' ) . $e->getMessage()));
2301 } catch (\NitroPack\SocketOpenException $e) {
2302 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Can\'t establish connection with NitroPack\'s servers', 'nitropack' )));
2303 } catch (\Exception $e) {
2304 nitropack_json_and_exit(array("status" => "error", "message" => __( 'Incorrect API credentials. Please make sure that you copied them correctly and try again.', 'nitropack' )));
2305 }
2306
2307 nitropack_json_and_exit(array("status" => "error"));
2308 }
2309
2310 function nitropack_reset_webhooks($nitroSDK) {
2311 $nitroSDK->getApi()->unsetWebhook("config");
2312 $nitroSDK->getApi()->unsetWebhook("cache_clear");
2313 $nitroSDK->getApi()->unsetWebhook("cache_ready");
2314 }
2315
2316 function nitropack_setup_webhooks($nitro, $token = NULL) {
2317 if (!$nitro || !$token) {
2318 throw new \NitroPack\SDK\WebhookException('Webhook token cannot be empty.');
2319 }
2320
2321 $homeUrl = strtolower(get_home_url());
2322 $configUrl = new \NitroPack\Url\Url($homeUrl . "?nitroWebhook=config&token=$token");
2323 $cacheClearUrl = new \NitroPack\Url\Url($homeUrl . "?nitroWebhook=cache_clear&token=$token");
2324 $cacheReadyUrl = new \NitroPack\Url\Url($homeUrl . "?nitroWebhook=cache_ready&token=$token");
2325
2326 $nitro->getApi()->setWebhook("config", $configUrl);
2327 $nitro->getApi()->setWebhook("cache_clear", $cacheClearUrl);
2328 $nitro->getApi()->setWebhook("cache_ready", $cacheReadyUrl);
2329 }
2330
2331 function nitropack_disconnect() {
2332 nitropack_uninstall_advanced_cache();
2333
2334 try {
2335 nitropack_event("disconnect");
2336 if (null !== $nitro = get_nitropack_sdk()) {
2337 nitropack_reset_webhooks($nitro);
2338 }
2339 } catch (\Exception $e) {
2340 }
2341
2342 get_nitropack()->unsetCurrentBlogConfig();
2343
2344 $hostingNoticeFile = nitropack_get_hosting_notice_file();
2345 if (file_exists($hostingNoticeFile)) {
2346 if (WP_DEBUG) {
2347 unlink($hostingNoticeFile);
2348 } else {
2349 @unlink($hostingNoticeFile);
2350 }
2351 }
2352 }
2353
2354 function nitropack_set_compression_ajax() {
2355 $compressionStatus = !empty($_POST["data"]["compressionStatus"]);
2356 update_option("nitropack-enableCompression", (int)$compressionStatus);
2357 nitropack_json_and_exit(array("status" => "success", "hasCompression" => $compressionStatus));
2358 }
2359
2360 function nitropack_set_auto_cache_purge_ajax() {
2361 $autoCachePurgeStatus = !empty($_POST["autoCachePurgeStatus"]);
2362 update_option("nitropack-autoCachePurge", (int)$autoCachePurgeStatus);
2363 }
2364
2365 function nitropack_set_cart_cache_ajax() {
2366 if (get_nitropack()->isConnected() && nitropack_render_woocommerce_cart_cache_option()) {
2367 $cartCacheStatus = (int) (!empty($_POST["cartCacheStatus"]));
2368
2369 if ($cartCacheStatus == 1) {
2370 nitropack_enable_cart_cache();
2371 } else {
2372 nitropack_disable_cart_cache();
2373 }
2374 }
2375
2376 nitropack_json_and_exit(array(
2377 "type" => "error",
2378 "message" => __( 'Error! There was an error while updating cart cache!', 'nitropack' )
2379 ));
2380 }
2381
2382 function nitropack_set_bb_cache_purge_sync_ajax() {
2383 $bbCacheSyncPurgeStatus = !empty($_POST["bbCachePurgeSyncStatus"]);
2384 update_option("nitropack-bbCacheSyncPurge", (int)$bbCacheSyncPurgeStatus);
2385 }
2386
2387 function nitropack_set_cacheable_post_types() {
2388 $currentCacheableObjectTypes = nitropack_get_cacheable_object_types();
2389 $cacheableObjectTypes = !empty($_POST["cacheableObjectTypes"]) ? $_POST["cacheableObjectTypes"] : array();
2390 update_option("nitropack-cacheableObjectTypes", $cacheableObjectTypes);
2391
2392 foreach ($currentCacheableObjectTypes as $objectType) {
2393 if (!in_array($objectType, $cacheableObjectTypes)) {
2394 nitropack_purge(NULL, "pageType:" . $objectType, "Optimizing '$objectType' pages was manually disabled");
2395 }
2396 }
2397
2398 nitropack_json_and_exit(array(
2399 "type" => "success",
2400 "message" => __( 'Success! Cacheable post types have been updated!', 'nitropack' )
2401 ));
2402 }
2403
2404 function nitropack_test_compression_ajax() {
2405 $hasCompression = true;
2406 try {
2407 if (\NitroPack\Integration\Hosting\Flywheel::detect()) { // Flywheel: Compression is enabled by default
2408 update_option("nitropack-enableCompression", 0);
2409 } else {
2410 require_once plugin_dir_path(__FILE__) . nitropack_trailingslashit('nitropack-sdk') . 'autoload.php';
2411 $http = new NitroPack\HttpClient\HttpClient(get_site_url());
2412 $http->setHeader("X-NitroPack-Request", 1);
2413 $http->timeout = 25;
2414 $http->fetch();
2415 $headers = $http->getHeaders();
2416 if (!empty($headers["content-encoding"]) && strtolower($headers["content-encoding"]) == "gzip") { // compression is present, so there is no need to enable it in NitroPack. We only check for GZIP, because this is the only supported compression in the HttpClient
2417 update_option("nitropack-enableCompression", 0);
2418 $hasCompression = true;
2419 } else { // no compression, we must enable it from NitroPack
2420 update_option("nitropack-enableCompression", 1);
2421 $hasCompression = false;
2422 }
2423 }
2424 update_option("nitropack-checkedCompression", 1);
2425 } catch (\Exception $e) {
2426 nitropack_json_and_exit(array("status" => "error"));
2427 }
2428
2429 nitropack_json_and_exit(array("status" => "success", "hasCompression" => $hasCompression));
2430 }
2431
2432 function nitropack_render_woocommerce_cart_cache_option() {
2433 return class_exists('WooCommerce');
2434 }
2435
2436 function nitropack_is_cart_cache_active() {
2437 $nitro = get_nitropack()->getSdk();
2438 if ($nitro) {
2439 $config = $nitro->getConfig();
2440 if (!empty($config->StatefulCache->Status) && !empty($config->StatefulCache->CartCache)) {
2441 return nitropack_is_cart_cache_available();
2442 }
2443 }
2444 return false;
2445 }
2446
2447 function nitropack_is_cart_cache_available() {
2448 $nitro = get_nitropack()->getSdk();
2449 if ($nitro) {
2450 $config = $nitro->getConfig();
2451 if (!empty($config->StatefulCache->isCartCacheAvailable)) {
2452 return true;
2453 }
2454 }
2455 return false;
2456 }
2457
2458 function nitropack_handle_compression_toggle($old_value, $new_value) {
2459 nitropack_update_blog_compression($new_value == 1);
2460 }
2461
2462 function nitropack_update_blog_compression($enableCompression = false) {
2463 if (get_nitropack()->isConnected()) {
2464 $siteConfig = nitropack_get_site_config();
2465 $siteId = $siteConfig["siteId"];
2466 $siteSecret = $siteConfig["siteSecret"];
2467 $blogId = get_current_blog_id();
2468 get_nitropack()->updateCurrentBlogConfig($siteId, $siteSecret, $blogId, $enableCompression);
2469 }
2470 }
2471
2472 function nitropack_enable_warmup() {
2473 if (null !== $nitro = get_nitropack_sdk()) {
2474 try {
2475 $nitro->getApi()->enableWarmup();
2476 $nitro->getApi()->setWarmupHomepage(get_home_url());
2477 $nitro->getApi()->runWarmup();
2478 } catch (\Exception $e) {
2479 }
2480
2481 nitropack_json_and_exit(array(
2482 "type" => "success",
2483 "message" => __( 'Success! Cache warmup has been enabled successfully!', 'nitropack' )
2484 ));
2485 }
2486
2487 nitropack_json_and_exit(array(
2488 "type" => "error",
2489 "message" => __( 'Error! There was an error while enabling the cache warmup!', 'nitropack' )
2490 ));
2491 }
2492
2493 function nitropack_disable_warmup() {
2494 if (null !== $nitro = get_nitropack_sdk()) {
2495 try {
2496 $nitro->getApi()->disableWarmup();
2497 $nitro->getApi()->resetWarmup();
2498 } catch (\Exception $e) {
2499 }
2500
2501 nitropack_json_and_exit(array(
2502 "type" => "success",
2503 "message" => __( 'Success! Cache warmup has been disabled successfully!', 'nitropack' )
2504 ));
2505 }
2506
2507 nitropack_json_and_exit(array(
2508 "type" => "error",
2509 "message" => __( 'Error! There was an error while disabling the cache warmup!', 'nitropack' )
2510 ));
2511 }
2512
2513 function nitropack_run_warmup() {
2514 if (null !== $nitro = get_nitropack_sdk()) {
2515 try {
2516 $nitro->getApi()->runWarmup();
2517 } catch (\Exception $e) {
2518 }
2519
2520 nitropack_json_and_exit(array(
2521 "type" => "success",
2522 "message" => __( 'Success! Cache warmup has been started successfully!', 'nitropack' )
2523 ));
2524 }
2525
2526 nitropack_json_and_exit(array(
2527 "type" => "error",
2528 "message" => __( 'Error! There was an error while starting the cache warmup!', 'nitropack' )
2529 ));
2530 }
2531
2532 function nitropack_estimate_warmup() {
2533 if (null !== $nitro = get_nitropack_sdk()) {
2534 try {
2535 if (!session_id()) {
2536 session_start();
2537 }
2538 $id = !empty($_POST["estId"]) ? preg_replace("/[^a-fA-F0-9]/", "", (string)$_POST["estId"]) : NULL;
2539 if ($id !== NULL && (!is_string($id) || $id != $_SESSION["nitroEstimateId"])) {
2540 nitropack_json_and_exit(array(
2541 "type" => "error",
2542 "message" => __( 'Error! Invalid estimation ID!', 'nitropack' )
2543 ));
2544 }
2545
2546 $nitro->getApi()->setWarmupHomepage(get_home_url());
2547 $optimizationsEstimate = $nitro->getApi()->estimateWarmup($id);
2548
2549 if ($id === NULL) {
2550 $_SESSION["nitroEstimateId"] = $optimizationsEstimate; // When id is NULL, $optimizationsEstimate holds the ID for the newly started estimate
2551 }
2552 } catch (\Exception $e) {
2553 }
2554
2555 nitropack_json_and_exit(array(
2556 "type" => "success",
2557 "res" => $optimizationsEstimate
2558 ));
2559 }
2560
2561 nitropack_json_and_exit(array(
2562 "type" => "error",
2563 "message" => __( 'Error! There was an error while estimating the cache warmup!', 'nitropack' )
2564 ));
2565 }
2566
2567 function nitropack_warmup_stats() {
2568 if (null !== $nitro = get_nitropack_sdk()) {
2569 try {
2570 $stats = $nitro->getApi()->getWarmupStats();
2571 } catch (\Exception $e) {
2572 nitropack_json_and_exit(array(
2573 "type" => "error",
2574 "message" => __( 'Error! There was an error while fetching warmup stats!', 'nitropack' )
2575 ));
2576 }
2577
2578 nitropack_json_and_exit(array(
2579 "type" => "success",
2580 "stats" => $stats
2581 ));
2582 }
2583
2584 nitropack_json_and_exit(array(
2585 "type" => "error",
2586 "message" => __( 'Error! There was an error while fetching warmup stats!', 'nitropack' )
2587 ));
2588 }
2589
2590 function nitropack_enable_safemode() {
2591 if (null !== $nitro = get_nitropack_sdk()) {
2592 try {
2593 $nitro->enableSafeMode();
2594 } catch (\Exception $e) {
2595 }
2596
2597 nitropack_cache_safemode_status(true);
2598 nitropack_json_and_exit(array(
2599 "type" => "success",
2600 "message" => __( 'Success! Safe mode has been enabled successfully!', 'nitropack' )
2601 ));
2602 }
2603
2604 nitropack_json_and_exit(array(
2605 "type" => "error",
2606 "message" => __( 'Error! There was an error while enabling safe mode!', 'nitropack' )
2607 ));
2608 }
2609
2610 function nitropack_disable_safemode() {
2611 if (null !== $nitro = get_nitropack_sdk()) {
2612 try {
2613 $nitro->disableSafeMode();
2614 } catch (\Exception $e) {
2615 }
2616
2617 nitropack_cache_safemode_status(false);
2618 nitropack_json_and_exit(array(
2619 "type" => "success",
2620 "message" => __( 'Success! Safe mode has been disabled successfully!', 'nitropack' )
2621 ));
2622 }
2623
2624 nitropack_json_and_exit(array(
2625 "type" => "error",
2626 "message" => __( 'Error! There was an error while disabling safe mode!', 'nitropack' )
2627 ));
2628 }
2629
2630 function nitropack_enable_cart_cache() {
2631 if (null !== $nitro = get_nitropack_sdk()) {
2632 try {
2633 $nitro->enableCartCache();
2634
2635 nitropack_json_and_exit(array(
2636 "type" => "success",
2637 "message" => __( 'Success! Cart cache has been enabled successfully!', 'nitropack' )
2638 ));
2639 } catch (\Exception $e) {
2640 }
2641 }
2642
2643 nitropack_json_and_exit(array(
2644 "type" => "error",
2645 "message" => __( 'Error! There was an error while enabling cart cache!', 'nitropack' )
2646 ));
2647 }
2648
2649 function nitropack_disable_cart_cache() {
2650 if (null !== $nitro = get_nitropack_sdk()) {
2651 try {
2652 $nitro->disableCartCache();
2653
2654 nitropack_json_and_exit(array(
2655 "type" => "success",
2656 "message" => __( 'Success! Cart cache has been disabled successfully!', 'nitropack' )
2657 ));
2658 } catch (\Exception $e) {
2659 }
2660 }
2661
2662 nitropack_json_and_exit(array(
2663 "type" => "error",
2664 "message" => __( 'Error! There was an error while disabling cart cache!', 'nitropack' )
2665 ));
2666 }
2667
2668 function nitropack_safemode_status() {
2669 if (null !== $nitro = get_nitropack_sdk()) {
2670 try {
2671 $isEnabled = $nitro->getApi()->isSafeModeEnabled();
2672 } catch (\Exception $e) {
2673 nitropack_cache_safemode_status();
2674 nitropack_json_and_exit(array(
2675 "type" => "error",
2676 "message" => __( 'Error! There was an error while fetching the status of safe mode!', 'nitropack' )
2677 ));
2678 }
2679
2680 nitropack_cache_safemode_status($isEnabled);
2681 nitropack_json_and_exit(array(
2682 "type" => "success",
2683 "isEnabled" => $isEnabled
2684 ));
2685 }
2686
2687 nitropack_cache_safemode_status();
2688 nitropack_json_and_exit(array(
2689 "type" => "error",
2690 "message" => __( 'Error! There was an error while fetching status of safe mode!', 'nitropack' )
2691 ));
2692 }
2693
2694 function nitropack_cache_safemode_status($operation = null) {
2695 $sm = "-1";
2696 if (is_bool($operation)) {
2697 $sm = $operation ? '1' : '0';
2698 }
2699 return update_option('nitropack-safeModeStatus', $sm);
2700 }
2701
2702 function nitropack_get_site_config() {
2703 return get_nitropack()->getSiteConfig();
2704 }
2705
2706 function get_nitropack() {
2707 return \NitroPack\WordPress\NitroPack::getInstance();
2708 }
2709
2710 function nitropack_event($event, $nitro = null, $additional_meta_data = null) {
2711 global $wp_version;
2712
2713 try {
2714 $eventUrl = get_nitropack_integration_url("extensionEvent", $nitro);
2715 $domain = !empty($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : "Unknown";
2716
2717 if (class_exists('WooCommerce')) {
2718 $platform = 'WooCommerce';
2719 } else {
2720 $platform = 'WordPress';
2721 }
2722
2723 $query_data = array(
2724 'event' => $event,
2725 'platform' => $platform,
2726 'platform_version' => $wp_version,
2727 'nitropack_extension_version' => NITROPACK_VERSION,
2728 'additional_meta_data' => $additional_meta_data ? json_encode($additional_meta_data) : "{}",
2729 'domain' => $domain
2730 );
2731
2732 $client = new NitroPack\HttpClient\HttpClient($eventUrl . '&' . http_build_query($query_data));
2733 $client->doNotDownload = true;
2734 $client->fetch();
2735 } catch (\Exception $e) {}
2736 }
2737
2738 function nitropack_get_wpconfig_path() {
2739 $configFilePath = nitropack_trailingslashit(ABSPATH) . "wp-config.php";
2740 if (!file_exists($configFilePath)) {
2741 $configFilePath = nitropack_trailingslashit(dirname(ABSPATH)) . "wp-config.php";
2742 $settingsFilePath = nitropack_trailingslashit(dirname(ABSPATH)) . "wp-settings.php"; // We need to check for this file to avoid confusion if the current installation is a nested directory of another WP installation. Refer to wp-load.php for more information.
2743 if (!file_exists($configFilePath) || file_exists($settingsFilePath)) {
2744 return false;
2745 }
2746 }
2747
2748 if (!is_writable($configFilePath)) {
2749 return false;
2750 }
2751
2752 return $configFilePath;
2753 }
2754
2755 function nitropack_get_htaccess_path() {
2756 $configFilePath = nitropack_trailingslashit(ABSPATH) . ".htaccess";
2757 if (!file_exists($configFilePath)) {
2758 return false;
2759 }
2760
2761 if (!is_writable($configFilePath)) {
2762 return false;
2763 }
2764
2765 return $configFilePath;
2766 }
2767
2768 function nitropack_detect_hosting() {
2769 if (\NitroPack\Integration\Hosting\Flywheel::detect()) {
2770 return "flywheel";
2771 } else if (\NitroPack\Integration\Hosting\Cloudways::detect()) {
2772 return "cloudways";
2773 } else if (\NitroPack\Integration\Hosting\WPEngine::detect()) {
2774 return "wpengine";
2775 } else if (\NitroPack\Integration\Hosting\SiteGround::detect()) {
2776 return "siteground";
2777 } else if (\NitroPack\Integration\Hosting\GoDaddyWPaaS::detect()) {
2778 return "godaddy_wpaas";
2779 } else if (\NitroPack\Integration\Hosting\GridPane::detect()) {
2780 return "gridpane";
2781 } else if (\NitroPack\Integration\Hosting\Kinsta::detect()) {
2782 return "kinsta";
2783 } else if (\NitroPack\Integration\Hosting\Closte::detect()) {
2784 return "closte";
2785 } else if (\NitroPack\Integration\Hosting\Pagely::detect()) {
2786 return "pagely";
2787 } else if (\NitroPack\Integration\Hosting\WPX::detect()) {
2788 return "wpx";
2789 } else if (\NitroPack\Integration\Hosting\Vimexx::detect()) {
2790 return "vimexx";
2791 } else if (\NitroPack\Integration\Hosting\Pressable::detect()) {
2792 return "pressable";
2793 } else if (\NitroPack\Integration\Hosting\RocketNet::detect()) {
2794 return "rocketnet";
2795 } else if (\NitroPack\Integration\Hosting\Savvii::detect()) {
2796 return "savvii";
2797 } else if (\NitroPack\Integration\Hosting\DreamHost::detect()) {
2798 return "dreamhost";
2799 } else {
2800 return "unknown";
2801 }
2802 }
2803
2804 function nitropack_removeCacheBustParam($content) {
2805 $content = preg_replace("/(\?|%26|&#0?38;|&#x0?26;|&(amp;)?)ignorenitro(%3D|=)[a-fA-F0-9]{32}(?!%26|&#0?38;|&#x0?26;|&(amp;)?)\/?/mu", "", $content);
2806 return preg_replace("/(\?|%26|&#0?38;|&#x0?26;|&(amp;)?)ignorenitro(%3D|=)[a-fA-F0-9]{32}(%26|&#0?38;|&#x0?26;|&(amp;)?)/mu", "$1", $content);
2807 }
2808
2809 function nitropack_handle_request($servedFrom = "unknown") {
2810 global $np_integrationSetupEvent;
2811
2812 if (isset($_GET["ignorenitro"])) {
2813 unset($_GET["ignorenitro"]);
2814 }
2815
2816 if (defined("NITROPACK_STRIP_IGNORENITRO") && NITROPACK_STRIP_IGNORENITRO && $_SERVER['REQUEST_URI'] != '') {
2817 $_SERVER['REQUEST_URI'] = nitropack_removeCacheBustParam($_SERVER['REQUEST_URI']);
2818 }
2819
2820 nitropack_header('Cache-Control: no-cache');
2821 do_action("nitropack_early_cache_headers"); // Overrides the Cache-Control header on supported platforms
2822 $isManageWpRequest = !empty($_GET["mwprid"]);
2823 $isWpCli = nitropack_is_wp_cli();
2824
2825 if ( file_exists(NITROPACK_CONFIG_FILE) && !empty($_SERVER["HTTP_HOST"]) && !empty($_SERVER["REQUEST_URI"]) && !$isManageWpRequest && !$isWpCli ) {
2826 try {
2827 $siteConfig = nitropack_get_site_config();
2828 if ( $siteConfig && null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
2829 if (is_valid_nitropack_webhook()) {
2830 nitropack_handle_webhook();
2831 } else if (is_valid_nitropack_beacon()) {
2832 nitropack_handle_beacon();
2833 } else if (is_valid_nitropack_heartbeat()) {
2834 nitropack_handle_heartbeat();
2835 } else {
2836 $GLOBALS["NitroPack.instance"] = $nitro;
2837
2838 if (nitropack_passes_cookie_requirements() || (nitropack_is_ajax() && !empty($_COOKIE["nitroCachedPage"])) ) {
2839 // Check whether the current URL is cacheable
2840 // If this is an AJAX request, check whether the referer is cachable - this is needed for cases when NitroPack's "Enabled URLs" option is being used to whitelist certain URLs.
2841 // If we are not checking the referer, the AJAX requests on these pages can fail.
2842 $urlToCheck = nitropack_is_ajax() && !empty($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : $nitro->getUrl();
2843 if ($nitro->isAllowedUrl($urlToCheck)) {
2844 add_filter( 'nonce_life', 'nitropack_extend_nonce_life' );
2845 }
2846 }
2847
2848 if (nitropack_passes_cookie_requirements() && apply_filters("nitropack_can_serve_cache", true)) {
2849 if ($nitro->isCacheAllowed()) {
2850 if (!nitropack_is_ajax()) {
2851 do_action("nitropack_cacheable_cache_headers");
2852 }
2853
2854 if (!empty($siteConfig["compression"])) {
2855 $nitro->enableCompression();
2856 }
2857
2858 if ($nitro->hasLocalCache()) {
2859 // TODO: Make this work so we can provide the reverse proxies with this information $remainingTtl = $nitr->pageCache->getRemainingTtl();
2860 do_action("nitropack_cachehit_cache_headers"); // TODO: Pass the remaining TTL here
2861 $cacheControlOverride = defined("NITROPACK_CACHE_CONTROL_OVERRIDE") ? NITROPACK_CACHE_CONTROL_OVERRIDE : NULL;
2862 if ($cacheControlOverride) {
2863 nitropack_header('Cache-Control: ' . $cacheControlOverride);
2864 }
2865
2866 nitropack_header('X-Nitro-Cache: HIT');
2867 nitropack_header('X-Nitro-Cache-From: ' . $servedFrom);
2868 $nitro->pageCache->readfile();
2869 exit;
2870 } else {
2871 // We need the following if..else block to handle bot requests which will not be firing our beacon
2872 if (nitropack_is_warmup_request()) {
2873 $nitro->hasRemoteCache("default"); // Only ping the API letting our service know that this page must be cached.
2874 exit; // No need to continue handling this request. The response is not important.
2875 } else if (nitropack_is_lighthouse_request() || nitropack_is_gtmetrix_request() || nitropack_is_pingdom_request()) {
2876 $nitro->hasRemoteCache("default"); // Ping the API letting our service know that this page must be cached.
2877 }
2878
2879 $nitro->pageCache->useInvalidated(true);
2880 if ($nitro->hasLocalCache()) {
2881 nitropack_header('X-Nitro-Cache: STALE');
2882 nitropack_header('X-Nitro-Cache-From: ' . $servedFrom);
2883 $nitro->pageCache->readfile();
2884 exit;
2885 } else {
2886 $nitro->pageCache->useInvalidated(false);
2887 }
2888 }
2889 }
2890 }
2891 }
2892 }
2893 } catch (\Exception $e) {
2894 // Do nothing, cache serving will be handled by nitropack_init
2895 }
2896 }
2897 }
2898
2899 function nitropack_is_dropin_cache_allowed() {
2900 $siteConfig = nitropack_get_site_config();
2901 return $siteConfig && empty($siteConfig["isEzoicActive"]);
2902 }
2903
2904 function nitropack_admin_bar_menu($wp_admin_bar){
2905 if (nitropack_is_amp_page()) return;
2906
2907
2908 $nitropackPluginNotices = nitropack_plugin_notices();
2909
2910 if($nitropackPluginNotices['error']){
2911 $pluginStatus = 'error';
2912 } else if ($nitropackPluginNotices['warning']){
2913 $pluginStatus = 'warning';
2914 } else {
2915 $pluginStatus = 'ok';
2916 }
2917
2918 if (!get_nitropack()->isConnected()) {
2919 $node = array(
2920 'id' => 'nitropack-top-menu',
2921 'title' => '&nbsp;&nbsp;<i style="" class="fa fa-circle nitro nitro-status nitro-status-error" aria-hidden="true"></i>&nbsp;&nbsp;NitroPack is disconnected',
2922 'href' => admin_url( 'options-general.php?page=nitropack' ),
2923 'meta' => array(
2924 'class' => 'custom-node-class'
2925 )
2926 );
2927
2928 $wp_admin_bar->add_node(
2929 array(
2930 'parent' => 'nitropack-top-menu',
2931 'id' => 'optimizations-plugin-status',
2932 'title' => __( 'Connect NitroPack&nbsp;&nbsp;', 'nitropack' ),
2933 'href' => admin_url( 'options-general.php?page=nitropack' ),
2934 'meta' => array(
2935 'class' => 'nitropack-plugin-status',
2936 )
2937 )
2938 );
2939 } else {
2940 $node = array(
2941 'id' => 'nitropack-top-menu',
2942 'title' => '&nbsp;&nbsp;<i style="" class="fa fa-circle nitro nitro-status nitro-status-'.$pluginStatus.'" aria-hidden="true"></i>&nbsp;&nbsp;NitroPack',
2943 'href' => admin_url( 'options-general.php?page=nitropack' ),
2944 'meta' => array(
2945 'class' => 'custom-node-class'
2946 )
2947 );
2948
2949 if(!is_admin()) { // menu otions available when browsing front-end pages
2950 $wp_admin_bar->add_node(
2951 array(
2952 'parent' => 'nitropack-top-menu',
2953 'id' => 'optimizations-invalidate-cache',
2954 'title' => __( 'Invalidate Cache for this page&nbsp;&nbsp;', 'nitropack' ),
2955 'href' => "#",
2956 'meta' => array(
2957 'class' => 'nitropack-invalidate-cache',
2958 )
2959 )
2960 );
2961
2962 $wp_admin_bar->add_node(
2963 array(
2964 'parent' => 'nitropack-top-menu',
2965 'id' => 'optimizations-purge-cache',
2966 'title' => __( 'Purge Cache for this page&nbsp;&nbsp;', 'nitropack' ),
2967 'href' => "#",
2968 'meta' => array(
2969 'class' => 'nitropack-purge-cache',
2970 )
2971 )
2972 );
2973 }
2974
2975 if ($pluginStatus != "ok") {
2976 $numberOfIssues = count($nitropackPluginNotices['error']) + count($nitropackPluginNotices['warning']);
2977 $wp_admin_bar->add_node(
2978 array(
2979 'parent' => 'nitropack-top-menu',
2980 'id' => 'optimizations-plugin-status',
2981 'title' => 'Issues&nbsp;&nbsp;<span style="color:#fff;background-color:#ca4a1f;border-radius:11px;padding: 2px 7px">' . $numberOfIssues . '</span>',
2982 'href' => admin_url( 'options-general.php?page=nitropack' ),
2983 'meta' => array(
2984 'class' => 'nitropack-plugin-status',
2985 )
2986 )
2987 );
2988 }
2989
2990 $notificationCount = count(get_nitropack()->Notifications->get('system'));
2991 if ($notificationCount) {
2992 $node['title'] .= '&nbsp;&nbsp;<span style="color:#fff;background-color:#72aee6;border-radius:11px;padding: 2px 7px">' . $notificationCount . '</span>';
2993 $wp_admin_bar->add_node(
2994 array(
2995 'parent' => 'nitropack-top-menu',
2996 'id' => 'nitropack-notifications',
2997 'title' => 'Notifications&nbsp;&nbsp;<span style="color:#fff;background-color:#72aee6;border-radius:11px;padding: 2px 7px">' . $notificationCount . '</span>',
2998 'href' => admin_url( 'options-general.php?page=nitropack' ),
2999 'meta' => array(
3000 'class' => 'nitropack-notifications',
3001 )
3002 )
3003 );
3004 }
3005 }
3006
3007 $wp_admin_bar->add_node($node);
3008 }
3009
3010 function nitropack_admin_bar_script($hook) {
3011 if (!nitropack_is_amp_page()) {
3012 wp_enqueue_script('nitropack_admin_bar_menu_script', plugin_dir_url(__FILE__) . 'view/javascript/admin_bar_menu.js?np_v=' . NITROPACK_VERSION, ['jquery'], false, true);
3013 wp_localize_script( 'nitropack_admin_bar_menu_script', 'frontendajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' )));
3014 }
3015 }
3016
3017 function nitropack_enqueue_load_fa() {
3018 if (!nitropack_is_amp_page()) {
3019 wp_enqueue_style( 'load-fa', plugin_dir_url(__FILE__) . 'view/stylesheet/fontawesome/font-awesome.min.css?np_v=' . NITROPACK_VERSION);
3020 }
3021 }
3022
3023 function enqueue_nitropack_admin_bar_menu_stylesheet() {
3024 if (!nitropack_is_amp_page()) {
3025 wp_enqueue_style( 'nitropack_admin_bar_menu_stylesheet', plugin_dir_url(__FILE__) . 'view/stylesheet/admin_bar_menu.css?np_v=' . NITROPACK_VERSION);
3026 }
3027 }
3028
3029 function nitropack_cookiepath() {
3030 $siteConfig = nitropack_get_site_config();
3031 $homeUrl = $siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url();
3032 $url = new \NitroPack\Url\Url($homeUrl);
3033 return $url ? $url->getPath() : "/";
3034 }
3035
3036 function nitropack_setcookie($name, $value, $expires = NULL, $options = []) {
3037 if (headers_sent()) return;
3038 $cookie_options = '';
3039 $cookie_path = nitropack_cookiepath();
3040
3041 if ($expires && is_numeric($expires)) {
3042 $options["Expires"] = date("D, d M Y H:i:s", (int)$expires) . ' GMT';
3043 }
3044
3045 if (empty($options["SameSite"])) {
3046 $options["SameSite"] = "Lax";
3047 }
3048
3049 foreach ($options as $optName => $optValue) {
3050 $cookie_options .= "$optName=$optValue; ";
3051 }
3052 nitropack_header("set-cookie: $name=$value; Path=$cookie_path; " . $cookie_options, false);
3053 }
3054
3055 function nitropack_header($header, $replace = true, $response_code = 0) {
3056 if (!nitropack_is_wp_cron() && !nitropack_is_wp_cli()) {
3057 header($header, $replace, $response_code);
3058 }
3059 }
3060
3061
3062 function nitropack_upgrade_handler($entity) {
3063 $np = 'nitropack/main.php';
3064 $trigger = $entity;
3065 if ($entity instanceof Plugin_Upgrader) {
3066 $trigger = $entity->plugin_info();
3067 if (!is_plugin_active($trigger)) {
3068 return;
3069 }
3070 }
3071
3072 if ($entity instanceof Theme_Upgrader) {
3073 if ($entity->theme_info()->Name === wp_get_theme()->Name) {
3074 nitropack_theme_handler('Theme updated');
3075 }
3076 return;
3077 }
3078
3079 if ($trigger !== $np) {
3080 $cookie_expires = date("D, d M Y H:i:s",time() + 600) . ' GMT';
3081 nitropack_setcookie('nitropack_apwarning', "1", time() + 600);
3082 }
3083 }
3084
3085 function nitropack_plugin_notices() {
3086 static $npPluginNotices = NULL;
3087
3088 if ($npPluginNotices !== NULL) {
3089 return $npPluginNotices;
3090 }
3091
3092 $errors = [];
3093 $warnings = [];
3094 $infos = [];
3095
3096 // Add conficting plugins errors
3097 $conflictingPlugins = nitropack_get_conflicting_plugins();
3098 foreach ($conflictingPlugins as $clashingPlugin) {
3099 $warnings[] = sprintf("It seems like %s is active. NitroPack and %s have overlapping functionality and can interfere with each other. Please deactivate %s for best results in NitroPack.", $clashingPlugin, $clashingPlugin, $clashingPlugin);
3100 }
3101
3102 // Add residual cache notices if found
3103 $residualCachePlugins = \NitroPack\Integration\Plugin\RC::detectThirdPartyCaches();
3104 foreach ($residualCachePlugins as $rcpName) {
3105 $warnings[] = sprintf("We found residual cache files from %s. These files can interfere with the caching process and must be deleted. <button class=\"btn btn-light btn-outline-secondary btn-sm\" nitropack-rc-data=\"%s\">Click here</button> to delete them now.", $rcpName, $rcpName);
3106 }
3107
3108 // Add plugins state notices
3109 if (isset($_COOKIE['nitropack_apwarning'])) {
3110 $cookie_path = nitropack_cookiepath();
3111 $warnings[] = "It seems plugins have been activated, deactivated or updated. It is recommended that you purge the cache to reflect the latest changes. <a class=\"btn-sm\" href=\"javascript:void(0);\" id=\"np-onstate-cache-purge\" class=\"acivate\" onclick=\"document.cookie = 'nitropack_apwarning=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=$cookie_path';window.location.reload();\"> Dismiss</a>";
3112 }
3113
3114 $nitropackIsConnected = get_nitropack()->isConnected();
3115
3116 if ($nitropackIsConnected) {
3117 if (nitropack_is_advanced_cache_allowed()) {
3118 if (!nitropack_has_advanced_cache()) {
3119 $advancedCacheFile = nitropack_trailingslashit(WP_CONTENT_DIR) . 'advanced-cache.php';
3120 if (!file_exists($advancedCacheFile) || strpos(file_get_contents($advancedCacheFile), "NITROPACK_ADVANCED_CACHE") === false) { // For some reason we get the notice right after connecting (even though the advanced-cache file is already in place). This check works around this issue :(
3121 if (nitropack_install_advanced_cache()) {
3122 $infos[] = __( 'The file /wp-content/advanced-cache.php was either missing or not the one generated by NitroPack. NitroPack re-installed its version of the file, so it can function properly. Possibly there is another active page caching plugin in your system. For correct operation, please deactivate any other page caching plugins.', 'nitropack' );
3123 } else {
3124 if (!nitropack_is_conflicting_plugin_active()) {
3125 $errors[] = __( 'The file /wp-content/advanced-cache.php cannot be created. Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' );
3126 }
3127 }
3128 }
3129 } else {
3130 if (!defined("NITROPACK_ADVANCED_CACHE_VERSION") || NITROPACK_VERSION != NITROPACK_ADVANCED_CACHE_VERSION) {
3131 if (!nitropack_install_advanced_cache()) {
3132 if (nitropack_is_conflicting_plugin_active()) {
3133 $errors[] = __( 'The file /wp-content/advanced-cache.php cannot be created because a conflicting plugin is active. Please make sure to disable all conflicting plugins.', 'nitropack' );
3134 } else {
3135 $errors[] = __( 'The file /wp-content/advanced-cache.php cannot be created. Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' );
3136 }
3137 }
3138 }
3139 }
3140 } else {
3141 if (nitropack_has_advanced_cache()) {
3142 nitropack_uninstall_advanced_cache();
3143 }
3144 }
3145
3146 if ( (!defined("WP_CACHE") || !WP_CACHE) ) {
3147 if (\NitroPack\Integration\Hosting\Flywheel::detect()) { // Flywheel: This is configured throught the FW control panel
3148 $warnings[] = __( "The WP_CACHE setting is not enabled. Please go to your FlyWheel control panel and enable this setting. You can find more information <a href='https://getflywheel.com/wordpress-support/how-to-enable-wp_cache/' target='_blank'>in this document</a>.", 'nitropack' );
3149 } else if (!nitropack_set_wp_cache_const(true)) {
3150 $errors[] = __( 'The WP_CACHE constant cannot be set in the wp-config.php file. This can lead to slower cache delivery. Please make sure that the /wp-config.php file is writable and refresh this page.', 'nitropack' );
3151 }
3152 }
3153
3154 if ( apply_filters('nitropack_needs_htaccess_changes', false) ) {
3155 if (!nitropack_set_htaccess_rules(true)) {
3156 $warnings[] = __( 'Unable to configure LiteSpeed specific rules for maximum performance. Please make sure your .htaccess file is writable or contact support.', 'nitropack' );
3157 }
3158 }
3159
3160 if ( !get_nitropack()->dataDirExists() && !get_nitropack()->initDataDir()) {
3161 $errors[] = __( 'The NitroPack data directory cannot be created. Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' );
3162 return [
3163 'error' => $errors,
3164 'warning' => $warnings,
3165 'info' => $infos
3166 ];
3167 }
3168
3169 $siteConfig = nitropack_get_site_config();
3170 $siteId = $siteConfig ? $siteConfig["siteId"] : NULL;
3171 $siteSecret = $siteConfig ? $siteConfig["siteSecret"] : NULL;
3172 $webhookToken = esc_attr( get_option('nitropack-webhookToken') );
3173 $blogId = get_current_blog_id();
3174 $isConfigOutdated = !nitropack_is_config_up_to_date();
3175
3176 if ( !get_nitropack()->Config->exists() && !get_nitropack()->updateCurrentBlogConfig($siteId, $siteSecret, $blogId)) {
3177 $errors[] = __( 'The NitroPack static config file cannot be created. Please make sure that the /wp-content/nitropack/ directory is writable and refresh this page.', 'nitropack' );
3178 } else if ( $isConfigOutdated ) {
3179 if (!get_nitropack()->updateCurrentBlogConfig($siteId, $siteSecret, $blogId)) {
3180 $errors[] = __( 'The NitroPack static config file cannot be updated. Please make sure that the /wp-content/nitropack/ directory is writable and refresh this page.', 'nitropack' );
3181 } else {
3182 if (!$siteConfig) {
3183 nitropack_event("update");
3184 } else {
3185 $prevVersion = !empty($siteConfig["pluginVersion"]) ? $siteConfig["pluginVersion"] : "1.1.4 or older";
3186 nitropack_event("update", null, array("previous_version" => $prevVersion));
3187
3188 if (empty($siteConfig["pluginVersion"]) || version_compare($siteConfig["pluginVersion"], "1.3", "<")) {
3189 if (!headers_sent()) {
3190 setcookie("nitropack_upgrade_to_1_3_notice", 1, time() + 3600);
3191 }
3192 $_COOKIE["nitropack_upgrade_to_1_3_notice"] = 1;
3193 }
3194 }
3195 }
3196
3197 try {
3198 nitropack_setup_webhooks(get_nitropack_sdk(), $webhookToken);
3199 } catch (\NitroPack\SDK\WebhookException $e) {
3200 $warnings[] = __( 'Unable to configure webhooks. This can impact the stability of the plugin. Please disconnect and connect again in order to retry configuring the webhooks.', 'nitropack' );
3201 }
3202 } else {
3203 $optionsMistmatch = false;
3204 if (array_key_exists('options_cache', $siteConfig)) {
3205 foreach (\NitroPack\WordPress\NitroPack::$optionsToCache as $opt) {
3206 if (is_array($opt)) {
3207 foreach ($opt as $option => $suboption) {
3208 if (empty($siteConfig['options_cache'][$option][$suboption]) || $siteConfig['options_cache'][$option][$suboption] != get_option($option)[$suboption]) {
3209 $optionsMistmatch = true;
3210 break 2;
3211 }
3212 }
3213 } else {
3214 if (!array_key_exists($opt, $siteConfig['options_cache']) || $siteConfig['options_cache'][$opt] != get_option($opt)) {
3215 $optionsMistmatch = true;
3216 break;
3217 }
3218 }
3219 }
3220 } else {
3221 $optionsMistmatch = true;
3222 }
3223
3224 if (
3225 $optionsMistmatch ||
3226 (!array_key_exists("isEzoicActive", $siteConfig) || $siteConfig["isEzoicActive"] !== \NitroPack\Integration\Plugin\Ezoic::isActive()) ||
3227 (!array_key_exists("isLateIntegrationInitRequired", $siteConfig) || $siteConfig["isLateIntegrationInitRequired"] !== nitropack_is_late_integration_init_required()) ||
3228 (!array_key_exists("isDlmActive", $siteConfig) || $siteConfig["isDlmActive"] !== \NitroPack\Integration\Plugin\DownloadManager::isActive()) ||
3229 (!array_key_exists("isAeliaCurrencySwitcherActive", $siteConfig) || $siteConfig["isAeliaCurrencySwitcherActive"] !== \NitroPack\Integration\Plugin\AeliaCurrencySwitcher::isActive()) ||
3230 (!array_key_exists("isWoocommerceActive", $siteConfig) || $siteConfig["isWoocommerceActive"] !== \NitroPack\Integration\Plugin\Woocommerce::isActive()) ||
3231 (!array_key_exists("isWoocommerceCacheHandlerActive", $siteConfig) || $siteConfig["isWoocommerceCacheHandlerActive"] !== \NitroPack\Integration\Plugin\WoocommerceCacheHandler::isActive())
3232 ) {
3233 if (!get_nitropack()->updateCurrentBlogConfig($siteId, $siteSecret, $blogId)) {
3234 $errors[] = __( 'The NitroPack static config file cannot be updated. Please make sure that the /wp-content/nitropack/ directory is writable and refresh this page.', 'nitropack' );
3235 }
3236 }
3237
3238 if (empty($_COOKIE["nitropack_webhook_sync"])) {
3239 if (null !== $nitro = get_nitropack_sdk() ) {
3240 try {
3241 if (!headers_sent()) {
3242 nitropack_setcookie("nitropack_webhook_sync", "1", time() + 300); // Do these checks in 5 minute intervals.
3243 }
3244 $configWebhook = $nitro->getApi()->getWebhook("config");
3245 if (!empty($configWebhook)) {
3246 $query = parse_url($configWebhook, PHP_URL_QUERY);
3247 if ($query) {
3248 parse_str($query, $webhookParams);
3249 if (empty($webhookParams["token"]) || $webhookParams["token"] != $webhookToken) {
3250 $warnings[] = "Connection problems have been detected. Most likely you have used the same API credentials to connect another website (e.g. dev or staging). Click here to restore the connection to this site &nbsp;<a href='#' id='nitro-restore-connection-btn' class='btn btn-primary btn-sm'>Restore connection</a>";
3251 }
3252 }
3253 }
3254 } catch (\Exception $e) {
3255 //Do nothing
3256 }
3257 }
3258 }
3259
3260 if (apply_filters('nitropack_should_modify_htaccess', false) && (empty($_SERVER["NitroPackHtaccessVersion"]) || NITROPACK_VERSION != $_SERVER["NitroPackHtaccessVersion"])) {
3261 if (!nitropack_set_htaccess_rules(true)) {
3262 $errors[] = "The .htaccess file cannot be modified. Please make sure that it is writable and refresh this page.";
3263 }
3264 }
3265 }
3266
3267 if (!empty($_COOKIE["nitropack_upgrade_to_1_3_notice"])) {
3268 $warnings[] = "Your new version of NitroPack has a new better way of recaching updated content. However it is incompatible with the page relationships built by your previous version. Please invalidate your cache manually one-time so that content updates start working with the updated logic. <a href='javascript:void(0);' onclick='document.cookie = \"nitropack_upgrade_to_1_3_notice=0; expires=Thu, 01 Jan 1970 00:00:01 GMT;\";jQuery(this).closest(\".is-dismissible\").hide();'>Dismiss</a>";
3269 }
3270
3271 if ( \NitroPack\Integration\Plugin\Cloudflare::isApoActive() && ! \NitroPack\Integration\Plugin\Cloudflare::isApoCacheByDeviceTypeEnabled() ) {
3272 $warnings[] = "It seems Cache By Device Type is not activate with the Cloudflare APO. It is recommended that you enable it for a more optimized experience.";
3273 }
3274 }
3275
3276 $npPluginNotices = [
3277 'error' => $errors,
3278 'warning' => $warnings,
3279 'info' => $infos
3280 ];
3281
3282 return $npPluginNotices;
3283 }
3284
3285 /**
3286 * Caches some options in the config so that we can access them before get_option() is defined
3287 * which is in advanced_cache.php, functions.php and Integrations
3288 */
3289 function nitropack_updated_option($option, $oldValue, $value) {
3290 $neededOptions = \NitroPack\WordPress\NitroPack::$optionsToCache;
3291 if (!in_array($option, $neededOptions)) return;
3292
3293 $np = get_nitropack();
3294 $siteConfig = $np->Config->get();
3295
3296 if (function_exists('get_home_url')) {
3297 $configKey = \NitroPack\WordPress\NitroPack::getConfigKey();
3298 $siteConfig[$configKey]['options_cache'][$option] = $value;
3299 $np->Config->set($siteConfig);
3300 }
3301 }
3302
3303 function nitropack_is_late_integration_init_required() {
3304 return \NitroPack\Integration\Plugin\NginxHelper::isActive() || \NitroPack\Integration\Plugin\Cloudflare::isApoActive();
3305 }
3306
3307 function nitropack_display_admin_notices() {
3308 $noticesArray = nitropack_plugin_notices();
3309 foreach($noticesArray as $type => $notices){
3310 switch($type) {
3311 case "error":
3312 $alertType = "danger";
3313 break;
3314 case "warning":
3315 $alertType = "warning";
3316 break;
3317 case "info":
3318 $alertType = "info";
3319 break;
3320 }
3321 foreach($notices as $notice){
3322 ?>
3323 <div class="alert alert-<?php echo $alertType; ?>">
3324 <?php echo _e($notice); ?>
3325 </div>
3326 <?php
3327 }
3328 }
3329 }
3330
3331 function nitropack_offer_safemode() {
3332 global $pagenow;
3333 if ($pagenow == 'plugins.php') {
3334 $smStatus = get_option('nitropack-safeModeStatus', "-1");
3335 if ($smStatus === "0") {
3336 add_action('admin_enqueue_scripts', function() {
3337 wp_enqueue_script( 'np_safemode', plugin_dir_url( __FILE__ ). 'view/javascript/np_safemode.js', array('jquery'));
3338 wp_enqueue_style('np_safemode', plugin_dir_url( __FILE__ ) . 'view/stylesheet/np_safemode.css');
3339 });
3340 add_action('admin_footer', function(){require_once NITROPACK_PLUGIN_DIR . 'view/safemode.php';});
3341 }
3342 }
3343 }
3344
3345 // Init integration action handlers
3346 $integration = NitroPack\Integration::getInstance();
3347 $integration->init();
3348