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