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