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