NitroPack - Version 1.5.5

Version Description

  • New Feature: Compatibility with Fastly
  • New Feature: Compatibility with Closte
  • New Feature: Compatibility with Beaver Builder's cache purge
  • New Feature: Compatibility with the Cookie Notice plugin
  • New Feature: Add generic compatibility with LiteSpeed servers
  • Improvement: Better efficiency in the API calls leading to less overhead in admin operations
  • Improvement: Vastly better support for popular cache proxies, making a much better use of existing infrastructure
  • Improvement: Better compatibility with WP Engine
  • Improvement: Better compatibility with Kinsta
  • Improvement: Better compatibility with SiteGround
  • Improvement: Better compatibility with Pagely
  • Improvement: Better compatibility with Cloudways
  • Improvement: Better compatibility with Flywheel
  • Improvement: Clear existing proxy cache when NitroPack is activated or deactivated
  • Improvement: Show more helper messages to guide the administrator in resolving detected issues
  • Improvement: Prevent duplicate connections which were previously causing the cache to get out of sync
  • Improvement: More granular and accurate detection of inventory updates in WooCommerce
  • Improvement: The safe mode prompt is now on the deactivate step
  • Improvement: Handle a specific case of Cloudflare's Flexible SSL coupled with a redirect
  • Bug fix: Resolve an issue with the WooCommerce PayPal Checkout Payment Gateway plugin
  • Bug fix: Various form submission issues have been resolved
  • Many bug fixes and stability improvements
Download this release

Release Info

Developer nitropack
Plugin Icon 128x128 NitroPack
Version 1.5.5
Comparing to
See all releases

Code changes from version 1.5.4 to 1.5.5

Files changed (53) hide show
  1. classes/Integration.php +145 -0
  2. classes/Integration/Hosting/Closte.php +12 -0
  3. classes/Integration/Hosting/Cloudways.php +49 -0
  4. classes/Integration/Hosting/Flywheel.php +45 -0
  5. classes/Integration/Hosting/GoDaddyWPaaS.php +39 -0
  6. classes/Integration/Hosting/GridPane.php +15 -0
  7. classes/Integration/Hosting/Hosting.php +16 -0
  8. classes/Integration/Hosting/Kinsta.php +45 -0
  9. classes/Integration/Hosting/Pagely.php +55 -0
  10. classes/Integration/Hosting/PagelyCachePurge.php +10 -0
  11. classes/Integration/Hosting/SiteGround.php +59 -0
  12. classes/Integration/Hosting/WPEngine.php +52 -0
  13. classes/Integration/Plugin/BeaverBuilder.php +22 -0
  14. classes/Integration/Plugin/CF_Helper.php +33 -0
  15. classes/Integration/Plugin/Cloudflare.php +60 -0
  16. classes/Integration/Plugin/CookieNotice.php +21 -0
  17. classes/Integration/Plugin/DownloadManager.php +23 -0
  18. classes/Integration/Plugin/Ezoic.php +44 -0
  19. classes/Integration/Plugin/NginxHelper.php +34 -0
  20. classes/Integration/Plugin/RC.php +83 -0
  21. classes/Integration/Plugin/ShortPixel.php +24 -0
  22. classes/Integration/Plugin/WPCacheHelper.php +13 -0
  23. classes/Integration/Plugin/WPRocket.php +41 -0
  24. classes/Integration/Server/Cloudflare.php +40 -0
  25. classes/Integration/Server/Fastly.php +37 -0
  26. classes/Integration/Server/LiteSpeed.php +85 -0
  27. constants.php +2 -1
  28. diagnostics.php +22 -10
  29. functions.php +278 -119
  30. integrations.php +11 -399
  31. main.php +14 -8
  32. nitropack-sdk/NitroPack/SDK/Filesystem.php +4 -6
  33. nitropack-sdk/NitroPack/SDK/NitroPack.php +24 -4
  34. nitropack-sdk/NitroPack/SDK/Pagecache.php +20 -4
  35. nitropack-sdk/NitroPack/SDK/StorageDriver/Disk.php +6 -2
  36. nitropack-sdk/NitroPack/SDK/StorageDriver/Redis.php +3 -2
  37. nitropack-sdk/nitro.start.php +8 -0
  38. nitropack-sdk/vendor/autoload.php +1 -1
  39. nitropack-sdk/vendor/composer/ClassLoader.php +3 -3
  40. nitropack-sdk/vendor/composer/autoload_classmap.php +0 -1
  41. nitropack-sdk/vendor/composer/autoload_real.php +5 -5
  42. nitropack-sdk/vendor/composer/autoload_static.php +3 -8
  43. nitropack-sdk/vendor/composer/installed.json +64 -72
  44. nitropack-sdk/vendor/nitropack/httpclient/src/HttpClient.php +0 -28
  45. nitropack-sdk/vendor/nitropack/httpclient/src/HttpClientMulti.php +1 -31
  46. readme.txt +26 -2
  47. uninstall.php +1 -1
  48. view/admin.php +25 -6
  49. view/dashboard.php +64 -9
  50. view/diag.php +2 -10
  51. view/javascript/np_safemode.js +72 -0
  52. view/safemode.tpl +19 -0
  53. view/stylesheet/np_safemode.css +107 -0
classes/Integration.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack;
4
+
5
+ class Integration {
6
+ private static $instance = NULL;
7
+ private static $purgeAllPending = false;
8
+ private static $purgeUrlPending = [];
9
+ private static $isInitialized = false;
10
+ private static $isInitializedStage = [];
11
+ private static $modules = [
12
+ "NitroPack/Integration/Hosting/Cloudways",
13
+ "NitroPack/Integration/Hosting/Flywheel",
14
+ "NitroPack/Integration/Hosting/WPEngine",
15
+ "NitroPack/Integration/Hosting/SiteGround",
16
+ "NitroPack/Integration/Hosting/GoDaddyWPaaS",
17
+ "NitroPack/Integration/Hosting/Kinsta",
18
+ "NitroPack/Integration/Hosting/Pagely",
19
+ "NitroPack/Integration/Server/LiteSpeed",
20
+ "NitroPack/Integration/Server/Fastly",
21
+ "NitroPack/Integration/Server/Cloudflare",
22
+ "NitroPack/Integration/Plugin/NginxHelper",
23
+ "NitroPack/Integration/Plugin/Cloudflare",
24
+ "NitroPack/Integration/Plugin/ShortPixel",
25
+ "NitroPack/Integration/Plugin/WPCacheHelper",
26
+ "NitroPack/Integration/Plugin/CookieNotice",
27
+ "NitroPack/Integration/Plugin/BeaverBuilder"
28
+ ];
29
+ private static $loadedModules = [];
30
+ private static $stage = "very_early";
31
+ private $siteConfig = [];
32
+ private $purgeUrls = [];
33
+ private $fullPurge = false;
34
+
35
+ public static function getInstance() {
36
+ if (!self::$instance) {
37
+ self::$instance = new Integration();
38
+ }
39
+ return self::$instance;
40
+ }
41
+
42
+ public function __construct() {
43
+ $this->siteConfig = nitropack_get_site_config();
44
+ }
45
+
46
+ public function getHosting() {
47
+ return $this->siteConfig && !empty($this->siteConfig["hosting"]) ? $this->siteConfig["hosting"] : "unknown";
48
+ }
49
+
50
+ public function init() {
51
+ if (self::$isInitialized) return true;
52
+
53
+ add_action( 'nitropack_integration_purge_url', [$this, "logUrlPurge"] );
54
+ add_action( 'nitropack_integration_purge_all', [$this, "logFullPurge"] );
55
+ add_action( 'shutdown', [$this, 'executeIntegrationPurges'], -999 );
56
+
57
+ $this->initModules(); // very_early init
58
+
59
+ $action = $this->getSetupAction();
60
+ if (did_action($action)) {
61
+ $this->initModules();
62
+ } else {
63
+ add_action($action, [$this, 'initModules']);
64
+ }
65
+
66
+ self::$isInitialized = true;
67
+ }
68
+
69
+ public function logUrlPurge($url) {
70
+ $this->purgeUrls[] = $url;
71
+ }
72
+
73
+ public function logFullPurge() {
74
+ $this->fullPurge = true;
75
+ }
76
+
77
+ public function initModules() {
78
+ if (!empty(self::$isInitializedStage[self::$stage])) return true;
79
+
80
+ foreach (self::$modules as $moduleName) {
81
+ $module = $this->loadModule($moduleName);
82
+ if ($module && $module->init(self::$stage)) {
83
+ // Modules which need to be initialized only once return NULL so they don't end up in this array
84
+ // This array holds only modules which need to have their init method called for each stage
85
+ self::$loadedModules[$moduleName] = $module;
86
+ }
87
+ }
88
+
89
+ self::$isInitializedStage[self::$stage] = true;
90
+
91
+ if (self::$stage == "very_early") {
92
+ self::$stage = "early";
93
+ } else if (self::$stage == "early") {
94
+ if ($this->siteConfig && empty($this->siteConfig["isLateIntegrationInitRequired"])) {
95
+ do_action(NITROPACK_INTEGRATIONS_ACTION);
96
+ }
97
+
98
+ // This is needed in order to load non-cache-related integrations like the one with ShortPixel and WooCommerce Geo Location.
99
+ if (did_action('plugins_loaded')) {
100
+ $this->lateInitModules();
101
+ } else {
102
+ add_action('plugins_loaded', [$this, 'lateInitModules']);
103
+ }
104
+ } else {
105
+ if ($this->siteConfig && !empty($this->siteConfig["isLateIntegrationInitRequired"])) {
106
+ do_action(NITROPACK_INTEGRATIONS_ACTION);
107
+ }
108
+ }
109
+ }
110
+
111
+ public function lateInitModules() {
112
+ self::$stage = "late";
113
+ $this->initModules();
114
+ }
115
+
116
+ public function executeIntegrationPurges() {
117
+ if ($this->fullPurge) {
118
+ do_action("nitropack_execute_purge_all");
119
+ } else {
120
+ foreach (array_unique($this->purgeUrls) as $url) {
121
+ do_action("nitropack_execute_purge_url", $url);
122
+ }
123
+ }
124
+ }
125
+
126
+ private function loadModule($name) {
127
+ if (isset(self::$loadedModules[$name])) return self::$loadedModules[$name];
128
+
129
+ $class = str_replace("/", "\\", $name);
130
+ if ($class::STAGE == self::$stage) {
131
+ $module = new $class();
132
+ return $module;
133
+ } else {
134
+ return NULL;
135
+ }
136
+ }
137
+
138
+ private function getSetupAction() {
139
+ if ($this->siteConfig && !empty($this->siteConfig["isLateIntegrationInitRequired"])) {
140
+ return "plugins_loaded";
141
+ }
142
+
143
+ return "muplugins_loaded";
144
+ }
145
+ }
classes/Integration/Hosting/Closte.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class Closte extends Hosting {
6
+ const STAGE = NULL;
7
+
8
+ public static function detect() {
9
+ return defined("CLOSTE_APP_ID");
10
+ }
11
+ }
12
+
classes/Integration/Hosting/Cloudways.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class Cloudways extends Hosting {
6
+ const STAGE = "very_early";
7
+
8
+ public static function detect() {
9
+ return array_key_exists("cw_allowed_ip", $_SERVER) || preg_match("~/home/.*?cloudways.*~", __FILE__);
10
+ }
11
+
12
+ public function init($stage) {
13
+ if ($this->getHosting() == "cloudways") {
14
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
15
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
16
+ add_action('nitropack_early_cache_headers', [$this, 'setCacheControl']);
17
+ add_action('nitropack_cacheable_cache_headers', [$this, 'setCacheControl']);
18
+ add_action('nitropack_cachehit_cache_headers', [$this, 'setCacheControl']);
19
+ }
20
+ }
21
+
22
+ public function purgeUrl($url) {
23
+ try {
24
+ $purger = new \NitroPack\SDK\Integrations\Varnish(array("127.0.0.1"), "URLPURGE");
25
+ $purger->purge($url);
26
+ } catch (\Exception $e) {
27
+ // Breeze exception
28
+ }
29
+ }
30
+
31
+ public function purgeAll() {
32
+ try {
33
+ $homepage = home_url().'/.*';
34
+ $purger = new \NitroPack\SDK\Integrations\Varnish(array("127.0.0.1"), "PURGE");
35
+ $purger->purge($homepage);
36
+ } catch (\Exception $e) {
37
+ // Exception
38
+ }
39
+ }
40
+
41
+ public function setCacheControl() {
42
+ header("Vary: sec-ch-ua-mobile");
43
+ if (isset($_SERVER["HTTP_SEC_CH_UA_MOBILE"])) {
44
+ header("Cache-Control: public, max-age=0, s-maxage=3600"); // needs to be like that instead of Cache-Control: no-cache in order to allow caching in the provided reverse proxy, but prevent the browsers from doing so
45
+ } else {
46
+ return;
47
+ }
48
+ }
49
+ }
classes/Integration/Hosting/Flywheel.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class Flywheel extends Hosting {
6
+ const STAGE = "early";
7
+
8
+ public static function detect() {
9
+ return defined("FLYWHEEL_PLUGIN_DIR");
10
+ }
11
+
12
+ public function init($stage) {
13
+ if ($this->getHosting() == "flywheel") {
14
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
15
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
16
+ }
17
+ }
18
+
19
+ public function purgeUrl($url) {
20
+ try {
21
+ $purger = new \NitroPack\SDK\Integrations\Varnish(array("127.0.0.1"), "PURGE");
22
+ $purger->purge($url);
23
+ } catch (\Exception $e) {
24
+ // Breeze exception
25
+ }
26
+ }
27
+
28
+ public function purgeAll() {
29
+ try {
30
+ if (function_exists("get_home_url")) {
31
+ $home = get_home_url();
32
+ } else {
33
+ $siteConfig = nitropack_get_site_config();
34
+ $home = "/";
35
+ if ($siteConfig && !empty($siteConfig["home_url"])) {
36
+ $home = $siteConfig["home_url"];
37
+ }
38
+ }
39
+ $purger = new \NitroPack\SDK\Integrations\Varnish(array("127.0.0.1"), "PURGE");
40
+ $purger->purge($home);
41
+ } catch (\Exception $e) {
42
+ // Exception
43
+ }
44
+ }
45
+ }
classes/Integration/Hosting/GoDaddyWPaaS.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class GoDaddyWPaaS extends Hosting {
6
+ const STAGE = "early";
7
+
8
+ public static function detect() {
9
+ return class_exists('\WPaaS\Plugin');
10
+ }
11
+
12
+ public function init($stage) {
13
+ if ($this->getHosting() == "godaddy_wpaas") {
14
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
15
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
16
+ }
17
+ }
18
+
19
+ public function purgeUrl($url) {
20
+ if (class_exists('\WPaaS\Plugin')) {
21
+ update_option( 'gd_system_last_cache_flush', time() );
22
+ $hosts = [\WPaaS\Plugin::vip()];
23
+ $url = preg_replace("/^https:\/\//", "http://", $url);
24
+ $purger = new \NitroPack\SDK\Integrations\Varnish($hosts, 'BAN');
25
+ $purger->purge($url);
26
+ return true;
27
+ }
28
+
29
+ return false;
30
+ }
31
+
32
+ public function purgeAll() {
33
+ $siteConfig = nitropack_get_site_config();
34
+ if ($siteConfig && !empty($siteConfig["home_url"])) {
35
+ return nitropack_wpaas_purge_url($siteConfig["home_url"]);
36
+ }
37
+ return false;
38
+ }
39
+ }
classes/Integration/Hosting/GridPane.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class GridPane extends Hosting {
6
+ const STAGE = NULL;
7
+
8
+ public static function detect() {
9
+ $configFilePath = nitropack_get_wpconfig_path();
10
+ if (!$configFilePath) return false;
11
+ return strpos(file_get_contents($configFilePath), 'GridPane Cache Settings') !== false;
12
+ }
13
+ }
14
+
15
+
classes/Integration/Hosting/Hosting.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class Hosting {
6
+ protected function getHosting() {
7
+ $siteConfig = nitropack_get_site_config();
8
+ if ($siteConfig && !empty($siteConfig["hosting"])) {
9
+ $hosting = $siteConfig["hosting"];
10
+ } else {
11
+ $hosting = nitropack_detect_hosting();
12
+ }
13
+
14
+ return $hosting;
15
+ }
16
+ }
classes/Integration/Hosting/Kinsta.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class Kinsta extends Hosting {
6
+ const STAGE = "early";
7
+
8
+ public static function detect() {
9
+ return defined("KINSTAMU_VERSION");
10
+ }
11
+
12
+ public function init($stage) {
13
+ if ($this->getHosting() == "kinsta") {
14
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
15
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
16
+ }
17
+ }
18
+
19
+ public function purgeUrl($url) {
20
+ try {
21
+ $data = array(
22
+ 'single|nitropack' => preg_replace( '@^https?://@', '', $url)
23
+ );
24
+ $httpClient = new \NitroPack\HttpClient("https://localhost/kinsta-clear-cache/v2/immediate");
25
+ $httpClient->setPostData($data);
26
+ $httpClient->fetch(true, "POST");
27
+ return true;
28
+ } catch (\Exception $e) {
29
+ }
30
+
31
+ return false;
32
+ }
33
+
34
+ public function purgeAll() {
35
+ try {
36
+ $httpClient = new \NitroPack\HttpClient("https://localhost/kinsta-clear-cache-all");
37
+ $httpClient->timeout = 5;
38
+ $httpClient->fetch();
39
+ return true;
40
+ } catch (\Exception $e) {
41
+ }
42
+
43
+ return false;
44
+ }
45
+ }
classes/Integration/Hosting/Pagely.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class Pagely extends Hosting {
6
+ const STAGE = "very_early";
7
+
8
+ public static function detect() {
9
+ return class_exists('\PagelyCachePurge') || isset($_SERVER["HTTP_X_PAGELY_SSL"]);
10
+ }
11
+
12
+ public function init($stage) {
13
+ if ($this->getHosting() == "pagely") {
14
+ switch ($stage) {
15
+ case "very_early":
16
+ add_action('nitropack_cacheable_cache_headers', [$this, 'addCacheControl']);
17
+ add_action('nitropack_cachehit_cache_headers', [$this, 'addCacheControl']);
18
+ return true;
19
+ case "early":
20
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
21
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
22
+ return true;
23
+ default:
24
+ return false;
25
+ }
26
+ }
27
+ }
28
+
29
+ public function purgeUrl($url) {
30
+ try {
31
+ $path = parse_url($url, PHP_URL_PATH);
32
+ if (class_exists("\PagelyCachePurge")) { // We need to have this check for clients that switch hosts
33
+ $pagely = new PagelyCachePurge();
34
+ $pagely->purgePath($path . "(.*)");
35
+ }
36
+ } catch (\Exception $e) {
37
+ // Pagely exception
38
+ }
39
+ }
40
+
41
+ public function purgeAll() {
42
+ try {
43
+ if (class_exists("\PagelyCachePurge")) { // We need to have this check for clients that switch hosts
44
+ $pagely = new PagelyCachePurge();
45
+ $pagely->purgeAll();
46
+ }
47
+ } catch (\Exception $e) {
48
+ // Pagely exception
49
+ }
50
+ }
51
+
52
+ public function addCacheControl() {
53
+ header("Cache-Control: public, max-age=0, s-maxage=3600");
54
+ }
55
+ }
classes/Integration/Hosting/PagelyCachePurge.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class PagelyCachePurge extends \PagelyCachePurge {
6
+ public function __construct() {
7
+ parent::__construct();
8
+ $this->deferred = false;
9
+ }
10
+ }
classes/Integration/Hosting/SiteGround.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class SiteGround extends Hosting {
6
+ const STAGE = "very_early";
7
+
8
+ public static function detect() {
9
+ $configFilePath = nitropack_get_wpconfig_path();
10
+ if (!$configFilePath) return false;
11
+ return strpos(file_get_contents($configFilePath), 'Added by SiteGround WordPress management system') !== false;
12
+ }
13
+
14
+ public function init($stage) {
15
+ if ($this->getHosting() == "siteground") {
16
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
17
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
18
+ add_action('nitropack_early_cache_headers', [$this, 'setCacheControl']);
19
+ add_action('nitropack_cacheable_cache_headers', [$this, 'allowProxyCache']);
20
+ add_action('nitropack_cachehit_cache_headers', [$this, 'allowProxyCache']);
21
+ }
22
+ }
23
+
24
+ public function purgeUrl($url) {
25
+ $urlObj = new \NitroPack\Url($url);
26
+ $purgeUrl = $urlObj->getHost() . $urlObj->getPath();
27
+ if ($urlObj->getQuery()) {
28
+ $purgeUrl .= "(.*)";
29
+ }
30
+
31
+ $purgeUrl = preg_replace("/^www\./", "", $purgeUrl);
32
+ $purgeUrl = "http://" . $purgeUrl;
33
+
34
+ try {
35
+ $hosts = ['127.0.0.1'];
36
+ $purger = new \NitroPack\SDK\Integrations\Varnish($hosts, 'PURGE');
37
+ $purger->purge($purgeUrl);
38
+ } catch (\Exception $e) {}
39
+
40
+ return true;
41
+ }
42
+
43
+ public function purgeAll() {
44
+ $siteConfig = nitropack_get_site_config();
45
+ if ($siteConfig && !empty($siteConfig["home_url"])) {
46
+ return nitropack_siteground_purge_url($siteConfig["home_url"]);
47
+ }
48
+ return false;
49
+ }
50
+
51
+ public function setCacheControl() {
52
+ header("Cache-Control: public, max-age=0, s-maxage=3600"); // needs to be like that instead of Cache-Control: no-cache in order to allow caching in the provided reverse proxy, but prevent the browsers from doing so
53
+ }
54
+
55
+ public function allowProxyCache() {
56
+ $this->setCacheControl();
57
+ header('X-Cache-Enabled: True');
58
+ }
59
+ }
classes/Integration/Hosting/WPEngine.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Hosting;
4
+
5
+ class WPEngine extends Hosting {
6
+ const STAGE = "early";
7
+
8
+ public static function detect() {
9
+ return !!getenv('IS_WPE');
10
+ }
11
+
12
+ public function init($stage) {
13
+ if ($this->getHosting() == "wpengine") {
14
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
15
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
16
+ }
17
+ }
18
+
19
+ public function purgeUrl($url) {
20
+ try {
21
+ $handler = function($paths) use($url) {
22
+ $wpe_path = parse_url($url, PHP_URL_PATH);
23
+ $wpe_query = parse_url($url, PHP_URL_QUERY);
24
+ $varnish_path = $wpe_path;
25
+ if (!empty($wpe_query)) {
26
+ $varnish_path .= '?' . $wpe_query;
27
+ }
28
+ if ($url && count($paths) == 1 && $paths[0] == ".*") {
29
+ return array($varnish_path);
30
+ }
31
+ return $paths;
32
+ };
33
+ add_filter( 'wpe_purge_varnish_cache_paths', $handler );
34
+ if (class_exists("\WpeCommon")) { // We need to have this check for clients that switch hosts
35
+ \WpeCommon::purge_varnish_cache();
36
+ }
37
+ remove_filter( 'wpe_purge_varnish_cache_paths', $handler );
38
+ } catch (\Exception $e) {
39
+ // WPE exception
40
+ }
41
+ }
42
+
43
+ public function purgeAll() {
44
+ try {
45
+ if (class_exists("\WpeCommon")) { // We need to have this check for clients that switch hosts
46
+ \WpeCommon::purge_varnish_cache();
47
+ }
48
+ } catch (\Exception $e) {
49
+ // WPE exception
50
+ }
51
+ }
52
+ }
classes/Integration/Plugin/BeaverBuilder.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class BeaverBuilder {
6
+ const STAGE = "late";
7
+
8
+ public static function isActive() {
9
+ return class_exists('\FLBuilder');
10
+ }
11
+
12
+ public function init($stage) {
13
+ if (self::isActive() && get_option("nitropack-bbCacheSyncPurge", 0)) {
14
+ add_action('fl_builder_cache_cleared', [$this, 'cachePurgeSync']);
15
+ return true;
16
+ }
17
+ }
18
+
19
+ public function cachePurgeSync() {
20
+ nitropack_purge(NULL, NULL, sprintf("Full cache purge due to cache sync with Beaver Builder."));
21
+ }
22
+ }
classes/Integration/Plugin/CF_Helper.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class CF_Helper extends \CF\WordPress\Hooks {
6
+ public function isApoEnabled() {
7
+ if (method_exists($this, "isAutomaticPlatformOptimizationEnabled")) {
8
+ return $this->isAutomaticPlatformOptimizationEnabled();
9
+ } else {
10
+ return false;
11
+ }
12
+ }
13
+
14
+ public function purgeUrl($url) {
15
+ $wpDomainList = $this->integrationAPI->getDomainList();
16
+ if (!count($wpDomainList)) {
17
+ return;
18
+ }
19
+ $wpDomain = $wpDomainList[0];
20
+ $urls = [$url];
21
+
22
+ $zoneTag = $this->api->getZoneTag($wpDomain);
23
+
24
+ if (isset($zoneTag) && !empty($urls)) {
25
+ $chunks = array_chunk($urls, 30);
26
+
27
+ foreach ($chunks as $chunk) {
28
+ $this->api->zonePurgeFiles($zoneTag, $chunk);
29
+ }
30
+ }
31
+ }
32
+ }
33
+
classes/Integration/Plugin/Cloudflare.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class Cloudflare {
6
+ const STAGE = "very_early";
7
+
8
+ public static function isApoActive() {
9
+ if (defined('CLOUDFLARE_PLUGIN_DIR')) {
10
+ $cfHelper = new CF_Helper();
11
+ return $cfHelper->isApoEnabled();
12
+ } else {
13
+ return false;
14
+ }
15
+ }
16
+
17
+ public static function isApoRequest() {
18
+ return !empty($_SERVER["HTTP_CF_DEVICE_TYPE"]);
19
+ }
20
+
21
+ public function init($stage) {
22
+ switch ($stage) {
23
+ case "very_early":
24
+ if (self::isApoRequest()) {
25
+ add_action('nitropack_cacheable_cache_headers', [$this, 'allowApoCache'], PHP_INT_MAX);
26
+ add_action('nitropack_cachehit_cache_headers', [$this, 'allowApoCache'], PHP_INT_MAX);
27
+ }
28
+ return true;
29
+ case "late":
30
+ if (self::isApoActive()) {
31
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
32
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
33
+ }
34
+ default:
35
+ return false;
36
+ }
37
+ }
38
+
39
+ public function purgeUrl($url) {
40
+ if (defined('CLOUDFLARE_PLUGIN_DIR')) {
41
+ $cfHelper = new CF_Helper();
42
+ return $cfHelper->purgeUrl($url);
43
+ } else {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ public function purgeAll() {
49
+ if (defined('CLOUDFLARE_PLUGIN_DIR')) {
50
+ $cfHelper = new CF_Helper();
51
+ return $cfHelper->purgeCacheEverything();
52
+ } else {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ public function allowApoCache() {
58
+ header("CDN-Cache-Control: public, max-age=300, s-maxage=300, stale-while-revalidate=3600");
59
+ }
60
+ }
classes/Integration/Plugin/CookieNotice.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class CookieNotice {
6
+ const STAGE = "late";
7
+
8
+ public function init($stage) {
9
+ # Cookie Notice plugin hack
10
+ add_action( 'init', function() {
11
+ $cookieNoticePath = 'cookie-notice/cookie-notice.php';
12
+ if (function_exists("is_plugin_active") && is_plugin_active($cookieNoticePath)) {
13
+ $agent = Cookie_Notice()->bot_detect->get_user_agent();
14
+ if ($agent) {
15
+ $replaced = str_replace('Nitro-Optimizer-Agent', '', $agent);
16
+ Cookie_Notice()->bot_detect->set_user_agent($replaced);
17
+ }
18
+ }
19
+ }, 5);
20
+ }
21
+ }
classes/Integration/Plugin/DownloadManager.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class DownloadManager {
6
+ const STAGE = NULL; // Don't run init
7
+
8
+ public static function isActive() {
9
+ return defined('DLM_VERSION');
10
+ }
11
+
12
+ public static function downloadingUrl() {
13
+ $downloadingPage = get_option("dlm_dp_downloading_page");
14
+ return $downloadingPage ? get_permalink($downloadingPage) : NULL;
15
+ }
16
+
17
+ public static function downloadEndpoint() {
18
+ $downloadEndpoint = get_option("dlm_download_endpoint");
19
+ return $downloadEndpoint ? nitropack_trailingslashit(get_home_url()) . $downloadEndpoint : NULL;
20
+ }
21
+ }
22
+
23
+
classes/Integration/Plugin/Ezoic.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class Ezoic {
6
+ const STAGE = NULL; // Don't run init
7
+
8
+ public static function isActive() {
9
+ return defined('EZOIC_INTEGRATION_VERSION');
10
+ }
11
+
12
+ public static function disable() {
13
+ global $wp_filter;
14
+ $hook = "shutdown";
15
+
16
+ if ( isset( $wp_filter[$hook]->callbacks ) ) {
17
+ array_walk( $wp_filter[$hook]->callbacks, function( $callbacks, $priority ) use ( &$hooks ) {
18
+ foreach ( $callbacks as $id => $callback ) {
19
+ $cb = $callback["function"];
20
+ if (is_callable($cb) && is_array($cb) && $cb[1] == "ez_buffer_end") {
21
+ remove_filter("shutdown", $cb, $priority);
22
+ register_shutdown_function('ob_end_flush');
23
+ }
24
+ }
25
+ });
26
+ }
27
+ }
28
+
29
+ public static function getHomeUrl($url) {
30
+ $siteConfig = nitropack_get_site_config();
31
+ if ( $siteConfig && null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
32
+ $nitroUrl = $nitro->getUrl();
33
+ $queryStart = strpos($nitroUrl, "?");
34
+ if ($queryStart !== false) {
35
+ return substr($nitroUrl, 0, $queryStart);
36
+ } else {
37
+ return $nitroUrl;
38
+ }
39
+ }
40
+
41
+ return $url;
42
+ }
43
+ }
44
+
classes/Integration/Plugin/NginxHelper.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class NginxHelper {
6
+ const STAGE = "late";
7
+
8
+ public static function isActive() {
9
+ return defined('NGINX_HELPER_BASEPATH');
10
+ }
11
+
12
+ public function init($stage) {
13
+ if (self::isActive()) {
14
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
15
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
16
+ }
17
+ }
18
+
19
+ public function purgeUrl($url) {
20
+ global $nginx_purger;
21
+ if ($nginx_purger) {
22
+ $nginx_purger->purge_url($url);
23
+ }
24
+ return true;
25
+ }
26
+
27
+ public function purgeAll() {
28
+ global $nginx_purger;
29
+ if ($nginx_purger) {
30
+ $nginx_purger->purge_all();
31
+ }
32
+ return true;
33
+ }
34
+ }
classes/Integration/Plugin/RC.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class RC {
6
+ public static $modules = [//Key should match the value from nitropack_get_conflicting_plugins() assigned to the $clashingPlugins array
7
+ 'WP-Rocket' => 'NitroPack\Integration\Plugin\WPRocket',
8
+ ];
9
+
10
+ public static function clearCache() {}
11
+
12
+ public static function dirHasContents($dir_path, $recursive_scan) {
13
+ $exclude_list = ['.', '..', '.htaccess', 'index.html'];
14
+ if (is_dir($dir_path)) {
15
+ $dir_path = nitropack_trailingslashit($dir_path);
16
+ $dir_contents = scandir($dir_path);
17
+ foreach ($dir_contents as $current_item) {
18
+ if (!in_array($current_item, $exclude_list)) {
19
+ $current_item_path = nitropack_trailingslashit($dir_path.$current_item);
20
+ if (is_dir($current_item_path)) {
21
+ if ($recursive_scan) {
22
+ if (self::dirHasContents($current_item_path, true)) return true;
23
+ } else {
24
+ return true;
25
+ }
26
+ } else {
27
+ return true;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+
35
+ public static function clearResidualCache($full_cache_path) {
36
+ try {
37
+ if (file_exists($full_cache_path)) {
38
+ if (is_dir($full_cache_path) && is_writable($full_cache_path)) {
39
+ $diskStorage = new \NitroPack\SDK\StorageDriver\Disk();
40
+ $diskStorage->deleteDir($full_cache_path);
41
+ return true;
42
+ }
43
+ return false;
44
+ }
45
+ } catch (\Exception $e) {
46
+ //TODO: Log the exception in a NP log
47
+ return false;
48
+ }
49
+ }
50
+
51
+ public static function getCurrentDomain() {
52
+ $url = new \NitroPack\Url(get_site_url());
53
+ return $url ? $url->getHost() : NULL;
54
+ }
55
+
56
+ public static function getWPCacheDir() {
57
+ $wpc_dir = nitropack_trailingslashit(defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : (defined('ABSPATH') ? ABSPATH . '/wp-content' : 'Undefined')) . 'cache';
58
+ if (file_exists($wpc_dir)) {
59
+ return $wpc_dir;
60
+ }
61
+ return false;
62
+ }
63
+
64
+ public static function isConflictingPluginActive($cp_name) {
65
+ $active_cp = nitropack_get_conflicting_plugins();
66
+ if (in_array($cp_name, $active_cp)) {
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+
72
+ public static function detectThirdPartyCaches() {
73
+ $residual_cache = array();
74
+
75
+ foreach (self::$modules as $module_name => $module) {
76
+ if (!self::isConflictingPluginActive($module_name) && $module::hasResidualCache()) {
77
+ $residual_cache[] = $module_name;
78
+ }
79
+ }
80
+
81
+ return $residual_cache;
82
+ }
83
+ }
classes/Integration/Plugin/ShortPixel.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class ShortPixel {
6
+ const STAGE = "late";
7
+
8
+ public function init($stage) {
9
+ if (defined('SHORTPIXEL_AI_VERSION')) { // ShortPixel
10
+ if (nitropack_is_ajax()) {
11
+ if (version_compare(SHORTPIXEL_AI_VERSION, "2", ">=")) { // ShortPixel AI 2.x
12
+ remove_action('wp_enqueue_scripts', array(\ShortPixelAI::_(), 'enqueue_script'));
13
+ remove_action('init', array(\ShortPixelAI::_(), 'init_ob'), 1);
14
+ remove_filter('script_loader_tag', array(\ShortPixelAI::_(), 'disable_rocket-Loader'), 10);
15
+ } else { // ShortPixel AI 1.x
16
+ remove_action('wp_enqueue_scripts', array(\ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'enqueue_script'), 11);
17
+ remove_action('init', array(\ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'init_ob'), 1);
18
+ remove_filter('rocket_css_content', array(\ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'parse_cached_css'), 10);
19
+ remove_filter('script_loader_tag', array(\ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'disable_rocket-Loader'), 10);
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
classes/Integration/Plugin/WPCacheHelper.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class WPCacheHelper {
6
+ const STAGE = "late";
7
+
8
+ public function init($stage) {
9
+ if (class_exists("\WC_Cache_Helper")) {
10
+ remove_action('template_redirect', array('WC_Cache_Helper', 'geolocation_ajax_redirect'));
11
+ }
12
+ }
13
+ }
classes/Integration/Plugin/WPRocket.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Plugin;
4
+
5
+ class WPRocket extends RC {
6
+
7
+ private static $cpath = ['/wp-rocket/' => false,]; //We are only interested in the page cache (other cache dirs '/busting/', '/critical-css/', '/min/')
8
+
9
+ public static function hasResidualCache() {
10
+ $wpc_dir = self::getWPCacheDir();
11
+ $curr_domain = self::getCurrentDomain();
12
+ if ($wpc_dir && $curr_domain) {
13
+ $prefix = defined('WP_ROCKET_CACHE_ROOT_PATH') ? nitropack_trailingslashit(WP_ROCKET_CACHE_ROOT_PATH) : $wpc_dir;
14
+ foreach (self::$cpath as $cp => $recursive_scan) {
15
+ $fcp = $prefix . $cp;
16
+ if ($cp === '/wp-rocket/') {
17
+ $fcp = $prefix . $cp . $curr_domain;
18
+ }
19
+ return self::dirHasContents($fcp, $recursive_scan);
20
+ }
21
+ }
22
+ return false;
23
+ }
24
+
25
+ public static function clearCache() {
26
+ $wpc_dir = self::getWPCacheDir();
27
+ $curr_domain = self::getCurrentDomain();
28
+ $result = array();
29
+ if ($wpc_dir && $curr_domain) {
30
+ $prefix = defined('WP_ROCKET_CACHE_ROOT_PATH') ? nitropack_trailingslashit(WP_ROCKET_CACHE_ROOT_PATH) : $wpc_dir;
31
+ foreach (self::$cpath as $cp => $recursive_scan) {
32
+ $fcp = $prefix . $cp;
33
+ if ($cp === '/wp-rocket/') {
34
+ $fcp = $prefix . $cp . $curr_domain;
35
+ }
36
+ $result[] = self::clearResidualCache($fcp);
37
+ }
38
+ }
39
+ return $result;
40
+ }
41
+ }
classes/Integration/Server/Cloudflare.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Server;
4
+
5
+ // We need this to control Cloudflare in addition to any other proxy potentially provided by the origin host company
6
+ class Cloudflare {
7
+ const STAGE = "very_early";
8
+
9
+ public static function detect() {
10
+ return !empty($_SERVER["HTTP_CF_CONNECTING_IP"]);
11
+ }
12
+
13
+ public static function isCacheEnabled() {
14
+ return self::detect() && !empty($_SERVER["HTTP_SEC_CH_UA_MOBILE"]);
15
+ }
16
+
17
+ public function init($stage) {
18
+ if (self::detect()) {
19
+ header("Accept-CH: Sec-CH-UA-Mobile");
20
+
21
+ if (self::isCacheEnabled()) {
22
+ add_action('nitropack_cacheable_cache_headers', [$this, 'allowProxyCache'], PHP_INT_MAX-1);
23
+ add_action('nitropack_cachehit_cache_headers', [$this, 'allowProxyCache'], PHP_INT_MAX-1);
24
+ } else {
25
+ add_action('nitropack_cacheable_cache_headers', [$this, 'preventProxyCache'], PHP_INT_MAX-1);
26
+ add_action('nitropack_cachehit_cache_headers', [$this, 'preventProxyCache'], PHP_INT_MAX-1);
27
+ }
28
+ }
29
+ }
30
+
31
+ public function allowProxyCache() {
32
+ header("Vary: sec-ch-ua-mobile");
33
+ header("CDN-Cache-Control: public, max-age=0, s-maxage=15, stale-while-revalidate=3600");
34
+ }
35
+
36
+ public function preventProxyCache() {
37
+ header("CDN-Cache-Control: no-cache");
38
+ }
39
+ }
40
+
classes/Integration/Server/Fastly.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Server;
4
+
5
+ class Fastly {
6
+ const STAGE = "very_early";
7
+
8
+ public static function detect() {
9
+ return !empty($_SERVER["HTTP_SURROGATE_CONTROL"]);
10
+ }
11
+
12
+ public static function isCacheEnabled() {
13
+ return self::detect() && !empty($_SERVER["HTTP_SEC_CH_UA_MOBILE"]);
14
+ }
15
+
16
+ public function init($stage) {
17
+ if (self::detect()) {
18
+ header("Accept-CH: Sec-CH-UA-Mobile");
19
+
20
+ if (self::isCacheEnabled()) {
21
+ add_action('nitropack_early_cache_headers', [$this, 'allowProxyCache']);
22
+ } else {
23
+ add_action('nitropack_early_cache_headers', [$this, 'preventProxyCache']);
24
+ }
25
+ }
26
+ }
27
+
28
+ public function allowProxyCache() {
29
+ header("Vary: sec-ch-ua-mobile");
30
+ header("Surrogate-Control: max-age=5, stale-while-revalidate=3600");
31
+ }
32
+
33
+ public function preventProxyCache() {
34
+ header("Surrogate-Control: max-age=0, must-revalidate");
35
+ }
36
+ }
37
+
classes/Integration/Server/LiteSpeed.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace NitroPack\Integration\Server;
4
+
5
+ class LiteSpeed {
6
+ const STAGE = "very_early";
7
+
8
+ public static function detect() {
9
+ return !empty($_SERVER["X-LSCACHE"]) || ( !empty($_SERVER["SERVER_SOFTWARE"]) && strtolower($_SERVER["SERVER_SOFTWARE"]) == "litespeed" );
10
+ }
11
+
12
+ public static function isCacheEnabled() {
13
+ return self::detect() && !empty($_SERVER["X-LSCACHE"]) && in_array("on", array_map("trim", explode(",", $_SERVER["X-LSCACHE"])));
14
+ }
15
+
16
+ public static function isCachePossible() {
17
+ return isset($_COOKIE["_lscache_vary_device"]);
18
+ }
19
+
20
+ public static function sendCacheHeader($maxAge = NULL) {
21
+ if (!$maxAge) {
22
+ header("X-LiteSpeed-Cache-Control: public");
23
+ } else if (is_numeric($maxAge)) {
24
+ header("X-LiteSpeed-Cache-Control: public,max-age=" . (int)$maxAge);
25
+ }
26
+ }
27
+
28
+ public static function purge($url = NULL, $tag = NULL) {
29
+ if ($url || $tag) {
30
+ $headerValues = [];
31
+
32
+ if ($url) {
33
+ $urlObj = new \NitroPack\Url((new \NitroPack\Url($url))->getNormalized());
34
+ if (!$urlObj->getQuery()) {
35
+ $headerValues[] = $urlObj->getPath();
36
+ } else {
37
+ $headerValues[] = $urlObj->getPath() . "?" . $urlObj->getQuery();
38
+ }
39
+ }
40
+
41
+ if ($tag) {
42
+ $headerValues[] = "tag=" . $tag;
43
+ }
44
+
45
+ header("X-LiteSpeed-Purge: " . implode(", ", $headerValues), false);
46
+ } else {
47
+ header("X-LiteSpeed-Purge: *", false);
48
+ }
49
+ }
50
+
51
+ public function init($stage) {
52
+ if (self::detect()) {
53
+ header("Accept-CH: Sec-CH-UA-Mobile");
54
+ }
55
+
56
+ if (self::isCacheEnabled()) {
57
+ add_action('nitropack_execute_purge_url', [$this, 'purgeUrl']);
58
+ add_action('nitropack_execute_purge_all', [$this, 'purgeAll']);
59
+ add_action('nitropack_cacheable_cache_headers', [$this, 'allowProxyCache']);
60
+ }
61
+ }
62
+
63
+ public function purgeUrl($url) {
64
+ self::purge($url);
65
+ }
66
+
67
+ public function purgeAll() {
68
+ self::purge();
69
+ }
70
+
71
+ public function allowProxyCache() {
72
+ header("X-LiteSpeed-Vary: cookie=_lscache_vary_device");
73
+ if (self::isCachePossible()) {
74
+ self::sendCacheHeader(3600);
75
+ } else if (!empty($_SERVER["HTTP_USER_AGENT"])) {
76
+ $device = new \NitroPack\SDK\Device($_SERVER["HTTP_USER_AGENT"]);
77
+ if ($device->isMobile()) {
78
+ nitropack_setcookie("_lscache_vary_device", "mobile", time() + 86400);
79
+ } else {
80
+ nitropack_setcookie("_lscache_vary_device", "desktop", time() + 86400);
81
+ }
82
+ }
83
+ }
84
+ }
85
+
constants.php CHANGED
@@ -6,11 +6,12 @@ function nitropack_trailingslashit($string) {
6
  return rtrim( $string, '/\\' ) . '/';
7
  }
8
 
9
- define( 'NITROPACK_VERSION', '1.5.4' );
10
  define( 'NITROPACK_OPTION_GROUP', 'nitropack' );
11
  define( 'NITROPACK_DATA_DIR', nitropack_trailingslashit(WP_CONTENT_DIR) . 'nitropack' );
12
  define( 'NITROPACK_CONFIG_FILE', nitropack_trailingslashit(NITROPACK_DATA_DIR) . 'config.json' );
13
  define( 'NITROPACK_PLUGIN_DIR', nitropack_trailingslashit(dirname(__FILE__)));
 
14
  define( 'NITROPACK_INTEGRATIONS_ACTION', "nitropack_integrations_ready");
15
  define( 'NITROPACK_HEARTBEAT_INTERVAL', 60*5); // 5min
16
 
6
  return rtrim( $string, '/\\' ) . '/';
7
  }
8
 
9
+ define( 'NITROPACK_VERSION', '1.5.5' );
10
  define( 'NITROPACK_OPTION_GROUP', 'nitropack' );
11
  define( 'NITROPACK_DATA_DIR', nitropack_trailingslashit(WP_CONTENT_DIR) . 'nitropack' );
12
  define( 'NITROPACK_CONFIG_FILE', nitropack_trailingslashit(NITROPACK_DATA_DIR) . 'config.json' );
13
  define( 'NITROPACK_PLUGIN_DIR', nitropack_trailingslashit(dirname(__FILE__)));
14
+ define( 'NITROPACK_CLASSES_DIR', nitropack_trailingslashit(NITROPACK_PLUGIN_DIR . 'classes') );
15
  define( 'NITROPACK_INTEGRATIONS_ACTION', "nitropack_integrations_ready");
16
  define( 'NITROPACK_HEARTBEAT_INTERVAL', 60*5); // 5min
17
 
diagnostics.php CHANGED
@@ -12,7 +12,7 @@ $np_diag_functions = array(
12
  'conflicting-plugins-status' => 'npdiag_get_conflicting_plugins',
13
  'user-config-status' => 'npdiag_get_user_config',
14
  'dir-info-status' => 'npdiag_get_dir_info',
15
- 'getexternalcache' => 'npdiag_get_third_party_cache'
16
 
17
  );
18
 
@@ -29,7 +29,10 @@ function npdiag_helper_compare_webhooks($nitro_sdk) {
29
  $storedWH = $nitro_sdk->getApi()->getWebhook("config");
30
  $matchResult = ($constructedWH == $storedWH) ? 'OK' : 'Warning: Webhooks do not match this site';
31
  } else {
32
- $matchResult = 'An empty SiteID was returned from site config.';
 
 
 
33
  }
34
  return $matchResult;
35
  } catch (\Exception $e) {
@@ -49,6 +52,9 @@ function npdiag_get_general_info() {
49
  } else {
50
  $probe_result = 'Error: Cannot get SDK instance';
51
  }
 
 
 
52
  $info = array(
53
  'Nitro_WP_version' => !empty($wp_version) ? $wp_version : get_bloginfo('version'),
54
  'Nitro_Version' => defined('NITROPACK_VERSION') ? NITROPACK_VERSION : 'Undefined',
@@ -60,7 +66,9 @@ function npdiag_get_general_info() {
60
  'Nitro_Plugin_Direcotry' => defined('NITROPACK_PLUGIN_DIR') ? NITROPACK_PLUGIN_DIR : dirname(__FILE__),
61
  'Nitro_Data_Directory' => defined('NITROPACK_DATA_DIR') ? NITROPACK_DATA_DIR : 'Undefined',
62
  'Nitro_Config_File' => defined('NITROPACK_CONFIG_FILE') ? NITROPACK_CONFIG_FILE : 'Undefined',
63
- 'Nitro_Webhooks' => $nitro ? npdiag_helper_compare_webhooks($nitro) : 'Error: Cannot get SDK instance'
 
 
64
  );
65
 
66
  if (defined("NITROPACK_VERSION") && defined("NITROPACK_ADVANCED_CACHE_VERSION") && NITROPACK_VERSION == NITROPACK_ADVANCED_CACHE_VERSION && nitropack_is_dropin_cache_allowed()) {
@@ -111,7 +119,7 @@ function npdiag_get_dir_info() {
111
  $siteID = !empty($siteConfig['siteId']) ? $siteConfig['siteId'] : get_option('nitropack-siteId');
112
  // DoI = Directories of Interest
113
  $DoI = array(
114
- 'WP_Content_Dir_Writable' => defined('WP_CONTENT_DIRR') ? WP_CONTENT_DIR : (defined('ABSPATH') ? ABSPATH . '/wp-content' : 'Undefined'),
115
  'Nitro_Data_Dir_Writable' => defined('NITROPACK_DATA_DIR') ? NITROPACK_DATA_DIR : npdiag_helper_trailingslashit(WP_CONTENT_DIR) . 'nitropack',
116
  'Nitro_siteID_Dir_Writable' => npdiag_helper_trailingslashit(WP_CONTENT_DIR) . 'nitropack/' . $siteID,
117
  'Nitro_Plugin_Dir_Writable' => defined('NITROPACK_PLUGIN_DIR') ? NITROPACK_PLUGIN_DIR : dirname(__FILE__)
@@ -131,11 +139,6 @@ function npdiag_get_dir_info() {
131
  return $info;
132
  }
133
 
134
- function npdiag_get_third_party_cache() {
135
- $info = "Get info about other caching solutions' residual cache. Placeholder for now.";
136
- return $info;
137
- }
138
-
139
  function npdiag_get_conflicting_plugins() {
140
  $info = nitropack_get_conflicting_plugins();
141
  if ( !empty($info) ) {
@@ -145,11 +148,20 @@ function npdiag_get_conflicting_plugins() {
145
  }
146
  }
147
 
 
 
 
 
 
 
 
 
 
148
  function nitropack_generate_report() {
149
  global $np_diag_functions;
150
  try {
151
  $ar = !empty($_POST["toggled"]) ? $_POST["toggled"] : NULL;
152
- if ( $ar !== NULL) {
153
  $diag_data = array('report-time-stamp' => date("Y-m-d H:i:s"));
154
  foreach ($ar as $func_name => $func_allowed) {
155
  if ((boolean)$func_allowed) {
12
  'conflicting-plugins-status' => 'npdiag_get_conflicting_plugins',
13
  'user-config-status' => 'npdiag_get_user_config',
14
  'dir-info-status' => 'npdiag_get_dir_info',
15
+ 'getexternalcache' => 'npdiag_detect_third_party_cache'
16
 
17
  );
18
 
29
  $storedWH = $nitro_sdk->getApi()->getWebhook("config");
30
  $matchResult = ($constructedWH == $storedWH) ? 'OK' : 'Warning: Webhooks do not match this site';
31
  } else {
32
+ $debugMsg = empty($_SERVER["HTTP_HOST"]) ? "HTTP_HOST is not defined. " : "";
33
+ $debugMsg .= empty($_SERVER["REQUEST_URI"]) ? "REQUEST_URI is not defined. " : "";
34
+ $debugMsg .= empty($debugMsg) ? 'URL used to match config was: ' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] : "";
35
+ $matchResult = 'Site config cannot be found, because ' . $debugMsg;
36
  }
37
  return $matchResult;
38
  } catch (\Exception $e) {
52
  } else {
53
  $probe_result = 'Error: Cannot get SDK instance';
54
  }
55
+
56
+ $third_party_residual_cache = npdiag_detect_third_party_cache();
57
+
58
  $info = array(
59
  'Nitro_WP_version' => !empty($wp_version) ? $wp_version : get_bloginfo('version'),
60
  'Nitro_Version' => defined('NITROPACK_VERSION') ? NITROPACK_VERSION : 'Undefined',
66
  'Nitro_Plugin_Direcotry' => defined('NITROPACK_PLUGIN_DIR') ? NITROPACK_PLUGIN_DIR : dirname(__FILE__),
67
  'Nitro_Data_Directory' => defined('NITROPACK_DATA_DIR') ? NITROPACK_DATA_DIR : 'Undefined',
68
  'Nitro_Config_File' => defined('NITROPACK_CONFIG_FILE') ? NITROPACK_CONFIG_FILE : 'Undefined',
69
+ 'Nitro_Webhooks' => $nitro ? npdiag_helper_compare_webhooks($nitro) : 'Error: Cannot get SDK instance',
70
+ 'Nitro_Connectivity_Requirements' => nitropack_check_func_availability('stream_socket_client') ? 'Yes' : 'Warning: "stream_socket_client" function is disabled.',
71
+ 'Residual_Cache_Found_For' => $third_party_residual_cache,
72
  );
73
 
74
  if (defined("NITROPACK_VERSION") && defined("NITROPACK_ADVANCED_CACHE_VERSION") && NITROPACK_VERSION == NITROPACK_ADVANCED_CACHE_VERSION && nitropack_is_dropin_cache_allowed()) {
119
  $siteID = !empty($siteConfig['siteId']) ? $siteConfig['siteId'] : get_option('nitropack-siteId');
120
  // DoI = Directories of Interest
121
  $DoI = array(
122
+ 'WP_Content_Dir_Writable' => defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : (defined('ABSPATH') ? ABSPATH . '/wp-content' : 'Undefined'),
123
  'Nitro_Data_Dir_Writable' => defined('NITROPACK_DATA_DIR') ? NITROPACK_DATA_DIR : npdiag_helper_trailingslashit(WP_CONTENT_DIR) . 'nitropack',
124
  'Nitro_siteID_Dir_Writable' => npdiag_helper_trailingslashit(WP_CONTENT_DIR) . 'nitropack/' . $siteID,
125
  'Nitro_Plugin_Dir_Writable' => defined('NITROPACK_PLUGIN_DIR') ? NITROPACK_PLUGIN_DIR : dirname(__FILE__)
139
  return $info;
140
  }
141
 
 
 
 
 
 
142
  function npdiag_get_conflicting_plugins() {
143
  $info = nitropack_get_conflicting_plugins();
144
  if ( !empty($info) ) {
148
  }
149
  }
150
 
151
+ function npdiag_detect_third_party_cache() {
152
+ $info = \NitroPack\Integration\Plugin\RC::detectThirdPartyCaches();
153
+ if ( !empty($info) ) {
154
+ return $info;
155
+ } else {
156
+ return $info = 'Not found';
157
+ }
158
+ }
159
+
160
  function nitropack_generate_report() {
161
  global $np_diag_functions;
162
  try {
163
  $ar = !empty($_POST["toggled"]) ? $_POST["toggled"] : NULL;
164
+ if ($ar !== NULL) {
165
  $diag_data = array('report-time-stamp' => date("Y-m-d H:i:s"));
166
  foreach ($ar as $func_name => $func_allowed) {
167
  if ((boolean)$func_allowed) {
functions.php CHANGED
@@ -106,24 +106,29 @@ function nitropack_uninstall_advanced_cache() {
106
  }
107
 
108
  function nitropack_set_wp_cache_const($status) {
109
- if (nitropack_is_flywheel()) { // Flywheel: This is configured throught the FW control panel
110
  return true;
111
  }
112
 
113
  $configFilePath = nitropack_trailingslashit(ABSPATH) . "wp-config.php";
114
- if (!file_exists($configFilePath)) {
115
  $configFilePath = nitropack_trailingslashit(dirname(ABSPATH)) . "wp-config.php";
116
  $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.
117
  if (!file_exists($configFilePath) || !is_writable($configFilePath) || file_exists($settingsFilePath)) {
118
  return false;
119
  }
120
- } else if (!is_writable($configFilePath)) {
 
 
121
  return false;
122
  }
123
 
124
  $newVal = sprintf("define( 'WP_CACHE', %s /* Modified by NitroPack */ );\n", ($status ? "true" : "false") );
125
  $replacementVal = sprintf(" %s /* Modified by NitroPack */ ", ($status ? "true" : "false") );
126
  $lines = file($configFilePath);
 
 
 
127
  $wpCacheFound = false;
128
  $phpOpeningTagLine = false;
129
 
@@ -196,6 +201,7 @@ function nitropack_handle_beacon() {
196
  if (!$hasLocalCache) {
197
  header("X-Nitro-Beacon: FORWARD");
198
  $hasCache = $nitro->hasRemoteCache($layout, false); // Download the new cache file
 
199
  printf("Cache %s", $hasCache ? "fetched" : "requested");
200
  } else {
201
  header("X-Nitro-Beacon: SKIP");
@@ -203,9 +209,11 @@ function nitropack_handle_beacon() {
203
  }
204
  }
205
 
206
- header("X-Nitro-Proxy-Purge: true");
207
- $nitro->purgeProxyCache($url);
208
- do_action('nitropack_integration_purge_url', $url);
 
 
209
  } catch (Exception $e) {
210
  // not a critical error, do nothing
211
  }
@@ -312,29 +320,29 @@ function nitropack_is_archive() {
312
  function nitropack_is_allowed_request() {
313
  global $np_queriedObj;
314
  $cacheableObjectTypes = nitropack_get_cacheable_object_types();
315
- if (!empty($cacheableObjectTypes)) {
316
  if (nitropack_is_home()) {
317
  if (!in_array('home', $cacheableObjectTypes)) {
318
- header("X-Nitro-Disabled-Reason: page type not allowed");
319
  return false;
320
  }
321
  } else {
322
  if (is_tax() || is_category() || is_tag()) {
323
  $np_queriedObj = get_queried_object();
324
  if (!empty($np_queriedObj) && !in_array($np_queriedObj->taxonomy, $cacheableObjectTypes)) {
325
- header("X-Nitro-Disabled-Reason: page type not allowed");
326
  return false;
327
  }
328
  } else {
329
  if (nitropack_is_archive()) {
330
  if (!in_array('archive', $cacheableObjectTypes)) {
331
- header("X-Nitro-Disabled-Reason: page type not allowed");
332
  return false;
333
  }
334
  } else {
335
  $postType = get_post_type();
336
  if (!empty($postType) && !in_array($postType, $cacheableObjectTypes)) {
337
- header("X-Nitro-Disabled-Reason: page type not allowed");
338
  return false;
339
  }
340
  }
@@ -353,7 +361,12 @@ function nitropack_is_allowed_request() {
353
  }
354
 
355
  function nitropack_is_ajax() {
356
- return (function_exists("wp_doing_ajax") && wp_doing_ajax()) || (defined('DOING_AJAX') && DOING_AJAX) || (!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest");
 
 
 
 
 
357
  }
358
 
359
  function nitropack_is_wp_cli() {
@@ -430,7 +443,6 @@ function nitropack_is_optimizer_request() {
430
 
431
  function nitropack_init() {
432
  global $np_queriedObj;
433
- header('Cache-Control: no-cache');
434
  header('X-Nitro-Cache: MISS');
435
  $GLOBALS["NitroPack.tags"] = array();
436
 
@@ -490,6 +502,9 @@ function nitropack_init() {
490
  if (!nitropack_is_optimizer_request() && nitropack_passes_page_requirements()) {// This is a cacheable URL
491
  add_action('wp_head', 'nitropack_print_telemetry_script');
492
  }
 
 
 
493
  }
494
  }
495
  }
@@ -599,6 +614,19 @@ function nitropack_get_beacon_script() {
599
  }
600
  }
601
 
 
 
 
 
 
 
 
 
 
 
 
 
 
602
  function nitropack_print_telemetry_script() {
603
  if (defined("NITROPACK_TELEMETRY_PRINTED")) return;
604
  define("NITROPACK_TELEMETRY_PRINTED", true);
@@ -713,6 +741,7 @@ function nitropack_options() {
713
  $siteSecret = esc_attr( get_option('nitropack-siteSecret') );
714
  $enableCompression = get_option('nitropack-enableCompression');
715
  $autoCachePurge = get_option('nitropack-autoCachePurge', 1);
 
716
  $checkedCompression = get_option('nitropack-checkedCompression');
717
  $cacheableObjectTypes = nitropack_get_cacheable_object_types();
718
 
@@ -813,6 +842,17 @@ function nitropack_get_conflicting_plugins() {
813
  }
814
  }
815
 
 
 
 
 
 
 
 
 
 
 
 
816
  return $clashingPlugins;
817
  }
818
 
@@ -833,6 +873,7 @@ function nitropack_admin_notices() {
833
  }
834
 
835
  nitropack_print_hosting_notice();
 
836
  }
837
 
838
  function nitropack_get_hosting_notice_file() {
@@ -846,23 +887,23 @@ function nitropack_print_hosting_notice() {
846
  $documentedHostingSetups = array(
847
  "flywheel" => array(
848
  "name" => "Flywheel",
849
- "helpUrl" => "https://help.nitropack.io/en/articles/4280090-delayed-content-updates-only-for-flywheel-hosting-users"
850
- ),
851
- "wpengine" => array(
852
- "name" => "WP Engine",
853
- "helpUrl" => "https://help.nitropack.io/en/articles/3639145-wp-engine-hosting-configuration-for-nitropack"
854
  ),
855
  "cloudways" => array(
856
  "name" => "Cloudways",
857
- "helpUrl" => "https://help.nitropack.io/en/articles/3582879-cloudways-hosting-configuration-for-nitropack"
858
  )
859
  );
860
 
861
  $siteConfig = nitropack_get_site_config();
862
  if ($siteConfig && !empty($siteConfig["hosting"]) && array_key_exists($siteConfig["hosting"], $documentedHostingSetups)) {
863
  $hostingInfo = $documentedHostingSetups[$siteConfig["hosting"]];
 
 
864
 
865
- nitropack_print_notice("info", sprintf("It looks like you are hosted on %s. Please follow <a href='%s' target='_blank'>these instructions</a> in order to make sure that everything works correctly. <a href='javascript:void(0);' onclick='jQuery.post(ajaxurl, {action: \"nitropack_dismiss_hosting_notice\"});jQuery(this).closest(\".is-dismissible\").hide();'>Dismiss</a>", $hostingInfo["name"], $hostingInfo["helpUrl"]));
 
 
866
  }
867
  }
868
 
@@ -875,6 +916,21 @@ function nitropack_dismiss_hosting_notice() {
875
  }
876
  }
877
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
878
  function nitropack_is_config_up_to_date() {
879
  $siteConfig = nitropack_get_site_config();
880
  return !empty($siteConfig) && !empty($siteConfig["pluginVersion"]) && $siteConfig["pluginVersion"] == NITROPACK_VERSION;
@@ -1334,6 +1390,9 @@ function nitropack_queue_sort($a, $b) {
1334
 
1335
  function nitropack_execute_purges() {
1336
  global $np_loggedPurges;
 
 
 
1337
  if (!empty($np_loggedPurges)) {
1338
  uasort($np_loggedPurges, "nitropack_queue_sort");
1339
  foreach ($np_loggedPurges as $requestKey => $data) {
@@ -1344,6 +1403,9 @@ function nitropack_execute_purges() {
1344
 
1345
  function nitropack_execute_invalidations() {
1346
  global $np_loggedInvalidations;
 
 
 
1347
  if (!empty($np_loggedInvalidations)) {
1348
  uasort($np_loggedInvalidations, "nitropack_queue_sort");
1349
  foreach ($np_loggedInvalidations as $requestKey => $data) {
@@ -1354,6 +1416,9 @@ function nitropack_execute_invalidations() {
1354
 
1355
  function nitropack_execute_warmups() {
1356
  global $np_loggedWarmups;
 
 
 
1357
  try {
1358
  if (!empty($np_loggedWarmups) && (null !== $nitro = get_nitropack_sdk())) {
1359
  $warmupStats = $nitro->getApi()->getWarmupStats();
@@ -1374,11 +1439,13 @@ function nitropack_fetch_config() {
1374
  }
1375
  }
1376
 
1377
- function nitropack_switch_theme() {
1378
  if (!get_option("nitropack-autoCachePurge", 1)) return;
1379
 
 
 
1380
  try {
1381
- nitropack_sdk_purge(NULL, NULL, 'Theme switched'); // purge entire cache
1382
  } catch (\Exception $e) {}
1383
  }
1384
 
@@ -1414,6 +1481,23 @@ function nitropack_invalidate_cache() {
1414
  ));
1415
  }
1416
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1417
  function nitropack_json_and_exit($array) {
1418
  if (nitropack_is_wp_cli()) {
1419
  $type = NULL;
@@ -1662,23 +1746,14 @@ function nitropack_handle_post_transition($new, $old, $post) {
1662
  }
1663
  }
1664
 
1665
- function nitropack_handle_product_stock_updates($product_id) {
1666
  if (!get_option("nitropack-autoCachePurge", 1)) return;
1667
 
1668
  try {
1669
- $post = get_post($product_id);
1670
- nitropack_clean_post_cache($post, NULL, true, sprintf("Invalidate product '%s' due to stock quantity change", $post->post_title)); // Update the product page and all related pages, because the quantity change might have to add/remove "Out of stock" labels
1671
- } catch (\Exception $e) {
1672
- // TODO: Log the error
1673
- }
1674
- }
1675
-
1676
- function nitropack_handle_product_price_updates($product_id) {
1677
- if (!get_option("nitropack-autoCachePurge", 1)) return;
1678
-
1679
- try {
1680
- $post = get_post($product_id);
1681
- nitropack_clean_post_cache($post, NULL, true, sprintf("Invalidate product '%s' due to price change", $post->post_title)); // Update the product page and all related pages, because the price change might have to be reflected on category pages
1682
  } catch (\Exception $e) {
1683
  // TODO: Log the error
1684
  }
@@ -1838,7 +1913,36 @@ function nitropack_verify_connect_ajax() {
1838
  nitropack_verify_connect($siteId, $siteSecret);
1839
  }
1840
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1841
  function nitropack_verify_connect($siteId, $siteSecret) {
 
 
 
 
1842
  if (empty($siteId) || empty($siteSecret)) {
1843
  nitropack_json_and_exit(array("status" => "error", "message" => "Site ID and Site Secret cannot be empty"));
1844
  }
@@ -1854,6 +1958,11 @@ function nitropack_verify_connect($siteId, $siteSecret) {
1854
  try {
1855
  $blogId = get_current_blog_id();
1856
  if (null !== $nitro = get_nitropack_sdk($siteId, $siteSecret, NULL, true)) {
 
 
 
 
 
1857
  $token = nitropack_generate_webhook_token($siteId);
1858
  update_option("nitropack-webhookToken", $token);
1859
  update_option("nitropack-enableCompression", -1);
@@ -1915,6 +2024,12 @@ function nitropack_verify_connect($siteId, $siteSecret) {
1915
  nitropack_json_and_exit(array("status" => "error"));
1916
  }
1917
 
 
 
 
 
 
 
1918
  function nitropack_setup_webhooks($nitro, $token = NULL) {
1919
  if (!$nitro || !$token) {
1920
  throw new \NitroPack\SDK\WebhookException('Webhook token cannot be empty.');
@@ -1933,6 +2048,9 @@ function nitropack_setup_webhooks($nitro, $token = NULL) {
1933
  function nitropack_disconnect() {
1934
  nitropack_uninstall_advanced_cache();
1935
  nitropack_event("disconnect");
 
 
 
1936
  nitropack_unset_current_blog_config();
1937
  delete_option("nitropack-siteId");
1938
  delete_option("nitropack-siteSecret");
@@ -1958,6 +2076,11 @@ function nitropack_set_auto_cache_purge_ajax() {
1958
  update_option("nitropack-autoCachePurge", (int)$autoCachePurgeStatus);
1959
  }
1960
 
 
 
 
 
 
1961
  function nitropack_set_cacheable_post_types() {
1962
  $currentCacheableObjectTypes = nitropack_get_cacheable_object_types();
1963
  $cacheableObjectTypes = !empty($_POST["cacheableObjectTypes"]) ? $_POST["cacheableObjectTypes"] : array();
@@ -1978,7 +2101,7 @@ function nitropack_set_cacheable_post_types() {
1978
  function nitropack_test_compression_ajax() {
1979
  $hasCompression = true;
1980
  try {
1981
- if (nitropack_is_flywheel()) { // Flywheel: Compression is enabled by default
1982
  update_option("nitropack-enableCompression", 0);
1983
  } else {
1984
  require_once plugin_dir_path(__FILE__) . nitropack_trailingslashit('nitropack-sdk') . 'autoload.php';
@@ -2141,6 +2264,7 @@ function nitropack_enable_safemode() {
2141
  } catch (\Exception $e) {
2142
  }
2143
 
 
2144
  nitropack_json_and_exit(array(
2145
  "type" => "success",
2146
  "message" => "Success! Safe mode has been enabled successfully!"
@@ -2160,6 +2284,7 @@ function nitropack_disable_safemode() {
2160
  } catch (\Exception $e) {
2161
  }
2162
 
 
2163
  nitropack_json_and_exit(array(
2164
  "type" => "success",
2165
  "message" => "Success! Safe mode has been disabled successfully!"
@@ -2177,24 +2302,35 @@ function nitropack_safemode_status() {
2177
  try {
2178
  $isEnabled = $nitro->getApi()->isSafeModeEnabled();
2179
  } catch (\Exception $e) {
 
2180
  nitropack_json_and_exit(array(
2181
  "type" => "error",
2182
  "message" => "Error! There was an error while fetching the status of safe mode!"
2183
  ));
2184
  }
2185
 
 
2186
  nitropack_json_and_exit(array(
2187
  "type" => "success",
2188
  "isEnabled" => $isEnabled
2189
  ));
2190
  }
2191
 
 
2192
  nitropack_json_and_exit(array(
2193
  "type" => "error",
2194
  "message" => "Error! There was an error while fetching status of safe mode!"
2195
  ));
2196
  }
2197
 
 
 
 
 
 
 
 
 
2198
  function nitropack_data_dir_exists() {
2199
  return defined("NITROPACK_DATA_DIR") && is_dir(NITROPACK_DATA_DIR);
2200
  }
@@ -2276,11 +2412,11 @@ function nitropack_update_current_blog_config($siteId, $siteSecret, $blogId, $en
2276
  "admin_url" => $admin_url,
2277
  "hosting" => $hosting,
2278
  "alwaysBuffer" => $alwaysBuffer,
2279
- "isEzoicActive" => nitropack_is_ezoic_active(),
2280
  "isLateIntegrationInitRequired" => nitropack_is_late_integration_init_required(),
2281
- "isDlmActive" => nitropack_is_dlm_active(),
2282
- "dlm_downloading_url" => nitropack_is_dlm_active() ? nitropack_dlm_downloading_url() : NULL,
2283
- "dlm_download_endpoint" => nitropack_is_dlm_active() ? nitropack_dlm_download_endpoint() : NULL,
2284
  "pluginVersion" => NITROPACK_VERSION
2285
  );
2286
  return nitropack_set_config($staticConfig);
@@ -2333,64 +2469,24 @@ function nitropack_get_wpconfig_path() {
2333
  return $configFilePath;
2334
  }
2335
 
2336
- function nitropack_is_flywheel() {
2337
- return defined("FLYWHEEL_PLUGIN_DIR");
2338
- }
2339
-
2340
- function nitropack_is_cloudways() {
2341
- return array_key_exists("cw_allowed_ip", $_SERVER) || preg_match("~/home/.*?cloudways.*~", __FILE__);
2342
- }
2343
-
2344
- function nitropack_is_wpe() {
2345
- return !!getenv('IS_WPE');
2346
- }
2347
-
2348
- function nitropack_is_wpaas() {
2349
- return class_exists('\WPaaS\Plugin');
2350
- }
2351
-
2352
- function nitropack_is_siteground() {
2353
- $configFilePath = nitropack_get_wpconfig_path();
2354
- if (!$configFilePath) return false;
2355
- return strpos(file_get_contents($configFilePath), 'Added by SiteGround WordPress management system') !== false;
2356
- }
2357
-
2358
- function nitropack_is_gridpane() {
2359
- $configFilePath = nitropack_get_wpconfig_path();
2360
- if (!$configFilePath) return false;
2361
- return strpos(file_get_contents($configFilePath), 'GridPane Cache Settings') !== false;
2362
- }
2363
-
2364
- function nitropack_is_kinsta() {
2365
- return defined("KINSTAMU_VERSION");
2366
- }
2367
-
2368
- function nitropack_is_closte() {
2369
- return defined("CLOSTE_APP_ID");
2370
- }
2371
-
2372
- function nitropack_is_pagely() {
2373
- return class_exists('\PagelyCachePurge');
2374
- }
2375
-
2376
  function nitropack_detect_hosting() {
2377
- if (nitropack_is_flywheel()) {
2378
  return "flywheel";
2379
- } else if (nitropack_is_cloudways()) {
2380
  return "cloudways";
2381
- } else if (nitropack_is_wpe()) {
2382
  return "wpengine";
2383
- } else if (nitropack_is_siteground()) {
2384
  return "siteground";
2385
- } else if (nitropack_is_wpaas()) {
2386
  return "godaddy_wpaas";
2387
- } else if (nitropack_is_gridpane()) {
2388
  return "gridpane";
2389
- } else if (nitropack_is_kinsta()) {
2390
  return "kinsta";
2391
- } else if (nitropack_is_closte()) {
2392
  return "closte";
2393
- } else if (nitropack_is_pagely()) {
2394
  return "pagely";
2395
  } else {
2396
  return "unknown";
@@ -2399,7 +2495,9 @@ function nitropack_detect_hosting() {
2399
 
2400
  function nitropack_handle_request($servedFrom = "unknown") {
2401
  global $np_integrationSetupEvent;
 
2402
  header('Cache-Control: no-cache');
 
2403
  $isManageWpRequest = !empty($_GET["mwprid"]);
2404
  $isWpCli = nitropack_is_wp_cli();
2405
 
@@ -2427,7 +2525,8 @@ function nitropack_handle_request($servedFrom = "unknown") {
2427
  }
2428
  } else {
2429
  $GLOBALS["NitroPack.instance"] = $nitro;
2430
- if (nitropack_passes_cookie_requirements()) {
 
2431
  // Check whether the current URL is cacheable
2432
  // 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.
2433
  // If we are not checking the referer, the AJAX requests on these pages can fail.
@@ -2435,21 +2534,22 @@ function nitropack_handle_request($servedFrom = "unknown") {
2435
  if ($nitro->isAllowedUrl($urlToCheck)) {
2436
  add_filter( 'nonce_life', 'nitropack_extend_nonce_life' );
2437
  }
 
2438
 
 
2439
  if ($nitro->isCacheAllowed()) {
 
 
 
 
2440
  if (!empty($siteConfig["compression"])) {
2441
  $nitro->enableCompression();
2442
  }
2443
 
2444
  if ($nitro->hasLocalCache()) {
 
 
2445
  $cacheControlOverride = defined("NITROPACK_CACHE_CONTROL_OVERRIDE") ? NITROPACK_CACHE_CONTROL_OVERRIDE : NULL;
2446
- if (!$cacheControlOverride && !empty($siteConfig["hosting"]) && in_array($siteConfig["hosting"], array("pagely", "siteground")) ) {
2447
- $cacheControlOverride = "public,max-age=30";
2448
- if ($siteConfig["hosting"] == "siteground") {
2449
- header('X-Cache-Enabled: True');
2450
- }
2451
- }
2452
-
2453
  if ($cacheControlOverride) {
2454
  header('Cache-Control: ' . $cacheControlOverride);
2455
  }
@@ -2492,15 +2592,6 @@ function nitropack_is_dropin_cache_allowed() {
2492
  return $siteConfig && empty($siteConfig["isEzoicActive"]);
2493
  }
2494
 
2495
- function nitropack_get_integration_setup_event() {
2496
- $siteConfig = nitropack_get_site_config();
2497
- if ($siteConfig && !empty($siteConfig["isLateIntegrationInitRequired"])) {
2498
- return "plugins_loaded";
2499
- }
2500
-
2501
- return "muplugins_loaded";
2502
- }
2503
-
2504
  function nitropack_admin_bar_menu($wp_admin_bar){
2505
 
2506
 
@@ -2603,6 +2694,54 @@ function enqueue_nitropack_admin_bar_menu_stylesheet() {
2603
  wp_enqueue_style( 'nitropack_admin_bar_menu_stylesheet', plugin_dir_url(__FILE__) . 'view/stylesheet/admin_bar_menu.css?np_v=' . NITROPACK_VERSION);
2604
  }
2605
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2606
  function nitropack_plugin_notices() {
2607
  static $npPluginNotices = NULL;
2608
 
@@ -2614,12 +2753,24 @@ function nitropack_plugin_notices() {
2614
  $warnings = [];
2615
  $infos = [];
2616
 
2617
- // Add conficting plugings errors
2618
  $conflictingPlugins = nitropack_get_conflicting_plugins();
2619
  foreach ($conflictingPlugins as $clashingPlugin) {
2620
  $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);
2621
  }
2622
 
 
 
 
 
 
 
 
 
 
 
 
 
2623
  $nitropackIsConnected = nitropack_is_connected();
2624
 
2625
  if ($nitropackIsConnected) {
@@ -2653,7 +2804,7 @@ function nitropack_plugin_notices() {
2653
  }
2654
 
2655
  if ( (!defined("WP_CACHE") || !WP_CACHE) ) {
2656
- if (nitropack_is_flywheel()) { // Flywheel: This is configured throught the FW control panel
2657
  $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>.";
2658
  } else if (!nitropack_set_wp_cache_const(true)) {
2659
  $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.";
@@ -2704,9 +2855,9 @@ function nitropack_plugin_notices() {
2704
  }
2705
  } else {
2706
  if (
2707
- (!array_key_exists("isEzoicActive", $siteConfig) || $siteConfig["isEzoicActive"] !== nitropack_is_ezoic_active()) ||
2708
  (!array_key_exists("isLateIntegrationInitRequired", $siteConfig) || $siteConfig["isLateIntegrationInitRequired"] !== nitropack_is_late_integration_init_required()) ||
2709
- (!array_key_exists("isDlmActive", $siteConfig) || $siteConfig["isDlmActive"] !== nitropack_is_dlm_active())
2710
  ) {
2711
  if (!nitropack_update_current_blog_config($siteId, $siteSecret, $blogId)) {
2712
  $errors[] = "The NitroPack static config file cannot be updated. Please make sure that the /wp-content/nitropack/ directory is writable and refresh this page.";
@@ -2717,7 +2868,7 @@ function nitropack_plugin_notices() {
2717
  if (null !== $nitro = get_nitropack_sdk() ) {
2718
  try {
2719
  if (!headers_sent()) {
2720
- setcookie("nitropack_webhook_sync", 1, time() + 300); // Do these checks in 5 minute intervals.
2721
  }
2722
  $configWebhook = $nitro->getApi()->getWebhook("config");
2723
  if (!empty($configWebhook)) {
@@ -2751,7 +2902,7 @@ function nitropack_plugin_notices() {
2751
  }
2752
 
2753
  function nitropack_is_late_integration_init_required() {
2754
- return nitropack_is_nginx_helper_active() || nitropack_is_apo_active();
2755
  }
2756
 
2757
  function nitropack_display_admin_notices() {
@@ -2778,11 +2929,19 @@ function nitropack_display_admin_notices() {
2778
  }
2779
  }
2780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2781
  // Init integration action handlers
2782
  require_once 'integrations.php';
2783
- $np_integrationSetupEvent = nitropack_get_integration_setup_event();
2784
- if (did_action($np_integrationSetupEvent)) {
2785
- nitropack_check_and_init_integrations();
2786
- } else {
2787
- add_action($np_integrationSetupEvent, 'nitropack_check_and_init_integrations');
2788
- }
106
  }
107
 
108
  function nitropack_set_wp_cache_const($status) {
109
+ if (\NitroPack\Integration\Hosting\Flywheel::detect()) { // Flywheel: This is configured throught the FW control panel
110
  return true;
111
  }
112
 
113
  $configFilePath = nitropack_trailingslashit(ABSPATH) . "wp-config.php";
114
+ if (!file_exists($configFilePath) || !is_writable($configFilePath)) {
115
  $configFilePath = nitropack_trailingslashit(dirname(ABSPATH)) . "wp-config.php";
116
  $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.
117
  if (!file_exists($configFilePath) || !is_writable($configFilePath) || file_exists($settingsFilePath)) {
118
  return false;
119
  }
120
+ }
121
+
122
+ if (!is_writable($configFilePath)) {
123
  return false;
124
  }
125
 
126
  $newVal = sprintf("define( 'WP_CACHE', %s /* Modified by NitroPack */ );\n", ($status ? "true" : "false") );
127
  $replacementVal = sprintf(" %s /* Modified by NitroPack */ ", ($status ? "true" : "false") );
128
  $lines = file($configFilePath);
129
+
130
+ if (empty($lines)) return false;
131
+
132
  $wpCacheFound = false;
133
  $phpOpeningTagLine = false;
134
 
201
  if (!$hasLocalCache) {
202
  header("X-Nitro-Beacon: FORWARD");
203
  $hasCache = $nitro->hasRemoteCache($layout, false); // Download the new cache file
204
+ $hasLocalCache = $hasCache;
205
  printf("Cache %s", $hasCache ? "fetched" : "requested");
206
  } else {
207
  header("X-Nitro-Beacon: SKIP");
209
  }
210
  }
211
 
212
+ if ($hasLocalCache || $proxyPurgeOnly) { // proxyPurgeOnly is set for unsupported browsers, in which case we need to purge the cache regardless of the existence of local NP cache
213
+ header("X-Nitro-Proxy-Purge: true");
214
+ $nitro->purgeProxyCache($url);
215
+ do_action('nitropack_integration_purge_url', $url);
216
+ }
217
  } catch (Exception $e) {
218
  // not a critical error, do nothing
219
  }
320
  function nitropack_is_allowed_request() {
321
  global $np_queriedObj;
322
  $cacheableObjectTypes = nitropack_get_cacheable_object_types();
323
+ if (is_array($cacheableObjectTypes)) {
324
  if (nitropack_is_home()) {
325
  if (!in_array('home', $cacheableObjectTypes)) {
326
+ header("X-Nitro-Disabled-Reason: page type not allowed (home)");
327
  return false;
328
  }
329
  } else {
330
  if (is_tax() || is_category() || is_tag()) {
331
  $np_queriedObj = get_queried_object();
332
  if (!empty($np_queriedObj) && !in_array($np_queriedObj->taxonomy, $cacheableObjectTypes)) {
333
+ header("X-Nitro-Disabled-Reason: page type not allowed ({$np_queriedObj->taxonomy})");
334
  return false;
335
  }
336
  } else {
337
  if (nitropack_is_archive()) {
338
  if (!in_array('archive', $cacheableObjectTypes)) {
339
+ header("X-Nitro-Disabled-Reason: page type not allowed (archive)");
340
  return false;
341
  }
342
  } else {
343
  $postType = get_post_type();
344
  if (!empty($postType) && !in_array($postType, $cacheableObjectTypes)) {
345
+ header("X-Nitro-Disabled-Reason: page type not allowed ($postType)");
346
  return false;
347
  }
348
  }
361
  }
362
 
363
  function nitropack_is_ajax() {
364
+ return
365
+ (function_exists("wp_doing_ajax") && wp_doing_ajax()) ||
366
+ (defined('DOING_AJAX') && DOING_AJAX) ||
367
+ (!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest") ||
368
+ (!empty($_SERVER["REQUEST_URI"]) && basename($_SERVER["REQUEST_URI"]) == "admin-ajax.php") ||
369
+ !empty($_GET["wc-ajax"]);
370
  }
371
 
372
  function nitropack_is_wp_cli() {
443
 
444
  function nitropack_init() {
445
  global $np_queriedObj;
 
446
  header('X-Nitro-Cache: MISS');
447
  $GLOBALS["NitroPack.tags"] = array();
448
 
502
  if (!nitropack_is_optimizer_request() && nitropack_passes_page_requirements()) {// This is a cacheable URL
503
  add_action('wp_head', 'nitropack_print_telemetry_script');
504
  }
505
+
506
+ add_action('wp_footer', 'nitropack_print_cookie_handler_script');
507
+ add_action('get_footer', 'nitropack_print_cookie_handler_script');
508
  }
509
  }
510
  }
614
  }
615
  }
616
 
617
+ function nitropack_print_cookie_handler_script() {
618
+ if (defined("NITROPACK_COOKIE_HANDLER_PRINTED")) return;
619
+ define("NITROPACK_COOKIE_HANDLER_PRINTED", true);
620
+ echo nitropack_get_cookie_handler_script();
621
+ }
622
+
623
+ function nitropack_get_cookie_handler_script() {
624
+ return "
625
+ <script nitro-exclude>
626
+ document.cookie = 'nitroCachedPage=' + (!window.NITROPACK_STATE ? '0' : '1') + '; path=/';
627
+ </script>";
628
+ }
629
+
630
  function nitropack_print_telemetry_script() {
631
  if (defined("NITROPACK_TELEMETRY_PRINTED")) return;
632
  define("NITROPACK_TELEMETRY_PRINTED", true);
741
  $siteSecret = esc_attr( get_option('nitropack-siteSecret') );
742
  $enableCompression = get_option('nitropack-enableCompression');
743
  $autoCachePurge = get_option('nitropack-autoCachePurge', 1);
744
+ $bbCacheSyncPurge = get_option('nitropack-bbCacheSyncPurge', 0);
745
  $checkedCompression = get_option('nitropack-checkedCompression');
746
  $cacheableObjectTypes = nitropack_get_cacheable_object_types();
747
 
842
  }
843
  }
844
 
845
+ if (class_exists('BJLL')) { // BJ Lazy Load
846
+ $clashingPlugins[] = "BJ Lazy Load";
847
+ }
848
+
849
+ if (defined('SHORTPIXEL_IMAGE_OPTIMISER_VERSION') && class_exists('\ShortPixel\ShortPixelPlugin')) { //ShortPixel WebP
850
+ $sp_config = \ShortPixel\ShortPixelPlugin::getInstance();
851
+ if ($sp_config->settings()->createWebp) {
852
+ $clashingPlugins[] = "ShortPixel WebP image creation";
853
+ }
854
+ }
855
+
856
  return $clashingPlugins;
857
  }
858
 
873
  }
874
 
875
  nitropack_print_hosting_notice();
876
+ nitropack_print_woocommerce_notice();
877
  }
878
 
879
  function nitropack_get_hosting_notice_file() {
887
  $documentedHostingSetups = array(
888
  "flywheel" => array(
889
  "name" => "Flywheel",
890
+ "helpUrl" => "https://getflywheel.com/wordpress-support/how-to-enable-wp_cache/"
 
 
 
 
891
  ),
892
  "cloudways" => array(
893
  "name" => "Cloudways",
894
+ "helpUrl" => "https://support.nitropack.io/hc/en-us/articles/360060916674-Cloudways-Hosting-Configuration-for-NitroPack"
895
  )
896
  );
897
 
898
  $siteConfig = nitropack_get_site_config();
899
  if ($siteConfig && !empty($siteConfig["hosting"]) && array_key_exists($siteConfig["hosting"], $documentedHostingSetups)) {
900
  $hostingInfo = $documentedHostingSetups[$siteConfig["hosting"]];
901
+ $showNotice = true;
902
+ if ($siteConfig["hosting"] == "flywheel" && defined("WP_CACHE") && WP_CACHE) $showNotice = false;
903
 
904
+ if ($showNotice) {
905
+ nitropack_print_notice("info", sprintf("It looks like you are hosted on %s. Please follow <a href='%s' target='_blank'>these instructions</a> in order to make sure that everything works correctly. <a href='javascript:void(0);' onclick='jQuery.post(ajaxurl, {action: \"nitropack_dismiss_hosting_notice\"});jQuery(this).closest(\".is-dismissible\").hide();'>Dismiss</a>", $hostingInfo["name"], $hostingInfo["helpUrl"]));
906
+ }
907
  }
908
  }
909
 
916
  }
917
  }
918
 
919
+ function nitropack_print_woocommerce_notice() {
920
+ if (nitropack_is_connected()) {
921
+ if (class_exists('WooCommerce')) {
922
+ $wcOneTimeNotice = get_option('nitropack-wcNotice');
923
+ if ($wcOneTimeNotice === false) {
924
+ nitropack_print_notice("success", "WooCommerce is detected. Your <strong>Account</strong>, <strong>cart</strong> and <strong>checkout</strong> pages are automatically excluded from optimization. <a href='javascript:void(0);' onclick='jQuery.post(ajaxurl, {action: \"nitropack_dismiss_woocommerce_notice\"});jQuery(this).closest(\".is-dismissible\").hide();'>Dismiss</a>");
925
+ }
926
+ }
927
+ }
928
+ }
929
+
930
+ function nitropack_dismiss_woocommerce_notice() {
931
+ update_option('nitropack-wcNotice', 1);
932
+ }
933
+
934
  function nitropack_is_config_up_to_date() {
935
  $siteConfig = nitropack_get_site_config();
936
  return !empty($siteConfig) && !empty($siteConfig["pluginVersion"]) && $siteConfig["pluginVersion"] == NITROPACK_VERSION;
1390
 
1391
  function nitropack_execute_purges() {
1392
  global $np_loggedPurges;
1393
+ if (!empty($_GET["action"]) && ($_GET["action"] === "edit") && !empty($_GET["meta-box-loader"])) {
1394
+ return;
1395
+ }
1396
  if (!empty($np_loggedPurges)) {
1397
  uasort($np_loggedPurges, "nitropack_queue_sort");
1398
  foreach ($np_loggedPurges as $requestKey => $data) {
1403
 
1404
  function nitropack_execute_invalidations() {
1405
  global $np_loggedInvalidations;
1406
+ if (!empty($_GET["action"]) && ($_GET["action"] === "edit") && !empty($_GET["meta-box-loader"])) {
1407
+ return;
1408
+ }
1409
  if (!empty($np_loggedInvalidations)) {
1410
  uasort($np_loggedInvalidations, "nitropack_queue_sort");
1411
  foreach ($np_loggedInvalidations as $requestKey => $data) {
1416
 
1417
  function nitropack_execute_warmups() {
1418
  global $np_loggedWarmups;
1419
+ if (!empty($_GET["action"]) && ($_GET["action"] === "edit") && !empty($_GET["meta-box-loader"])) {
1420
+ return;
1421
+ }
1422
  try {
1423
  if (!empty($np_loggedWarmups) && (null !== $nitro = get_nitropack_sdk())) {
1424
  $warmupStats = $nitro->getApi()->getWarmupStats();
1439
  }
1440
  }
1441
 
1442
+ function nitropack_theme_handler($event = NULL) {
1443
  if (!get_option("nitropack-autoCachePurge", 1)) return;
1444
 
1445
+ $msg = $event ? $event : 'Theme switched';
1446
+
1447
  try {
1448
+ nitropack_sdk_purge(NULL, NULL, $msg); // purge entire cache
1449
  } catch (\Exception $e) {}
1450
  }
1451
 
1481
  ));
1482
  }
1483
 
1484
+ function nitropack_clear_residual_cache() {
1485
+ $gde = !empty($_POST["gde"]) ? $_POST["gde"] : NULL;
1486
+ if ($gde && array_key_exists($gde, NitroPack\Integration\Plugin\RC::$modules)) {
1487
+ $result = NitroPack\Integration\Plugin\RC::$modules[$gde]::clearCache();
1488
+ if (!in_array(false, $result)) {
1489
+ nitropack_json_and_exit(array(
1490
+ "type" => "success",
1491
+ "message" => "Success! The residual cache has been cleared successfully!"
1492
+ ));
1493
+ }
1494
+ }
1495
+ nitropack_json_and_exit(array(
1496
+ "type" => "error",
1497
+ "message" => "Error! There was an error clearing the residual cache!"
1498
+ ));
1499
+ }
1500
+
1501
  function nitropack_json_and_exit($array) {
1502
  if (nitropack_is_wp_cli()) {
1503
  $type = NULL;
1746
  }
1747
  }
1748
 
1749
+ function nitropack_handle_product_updates($product, $updated) {
1750
  if (!get_option("nitropack-autoCachePurge", 1)) return;
1751
 
1752
  try {
1753
+ $post = get_post($product->get_id());
1754
+ $reasons = 'updated ';
1755
+ $reasons .= implode(',', $updated);
1756
+ 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
 
 
 
 
 
 
 
 
 
1757
  } catch (\Exception $e) {
1758
  // TODO: Log the error
1759
  }
1913
  nitropack_verify_connect($siteId, $siteSecret);
1914
  }
1915
 
1916
+ function nitropack_check_func_availability($func_name) {
1917
+ if (function_exists('ini_get')) {
1918
+ $existsResult = stripos(ini_get('disable_functions'), $func_name) === false;
1919
+ } else {
1920
+ $existsResult = function_exists($func_name);
1921
+ }
1922
+ return $existsResult;
1923
+ }
1924
+
1925
+ function nitropack_prevent_connecting($nitroSDK) {
1926
+ $remoteUrl = $nitroSDK->getApi()->getWebhook("config");
1927
+ if (empty($remoteUrl)) {
1928
+ return false;
1929
+ }
1930
+ $siteConfig = nitropack_get_site_config();
1931
+ $localUrl = new \NitroPack\Url($siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url());
1932
+ $localHome = strtolower($localUrl->getHost() . $localUrl->getPath());
1933
+ $storedUrl = new \NitroPack\Url($remoteUrl);
1934
+ $remoteHome = strtolower($storedUrl->getHost() . $storedUrl->getPath());
1935
+ if ($localHome === $remoteHome) {
1936
+ return false;
1937
+ }
1938
+ return array('local' => $localHome, 'remote' => $remoteHome);
1939
+ }
1940
+
1941
  function nitropack_verify_connect($siteId, $siteSecret) {
1942
+ if (!nitropack_check_func_availability('stream_socket_client')) {
1943
+ nitropack_json_and_exit(array("status" => "error", "message" => "stream_socket_client function is not allowed by your host. <a href=\"https://support.nitropack.io/hc/en-us/articles/360020898137\" target=\"_blank\" rel=\"noreferrer noopener\">Read more</a>"));
1944
+ }
1945
+
1946
  if (empty($siteId) || empty($siteSecret)) {
1947
  nitropack_json_and_exit(array("status" => "error", "message" => "Site ID and Site Secret cannot be empty"));
1948
  }
1958
  try {
1959
  $blogId = get_current_blog_id();
1960
  if (null !== $nitro = get_nitropack_sdk($siteId, $siteSecret, NULL, true)) {
1961
+ $preventParing = apply_filters('nitropack_prevent_connect', nitropack_prevent_connecting($nitro));
1962
+ if ($preventParing) {
1963
+ nitropack_json_and_exit(array("status" => "error", "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/>
1964
+ <a href='https://support.nitropack.io/hc/en-us/articles/4405254569745' target='_blank' rel='noreferrer noopener'>Read more</a>"));
1965
+ }
1966
  $token = nitropack_generate_webhook_token($siteId);
1967
  update_option("nitropack-webhookToken", $token);
1968
  update_option("nitropack-enableCompression", -1);
2024
  nitropack_json_and_exit(array("status" => "error"));
2025
  }
2026
 
2027
+ function nitropack_reset_webhooks($nitroSDK) {
2028
+ $nitroSDK->getApi()->unsetWebhook("config");
2029
+ $nitroSDK->getApi()->unsetWebhook("cache_clear");
2030
+ $nitroSDK->getApi()->unsetWebhook("cache_ready");
2031
+ }
2032
+
2033
  function nitropack_setup_webhooks($nitro, $token = NULL) {
2034
  if (!$nitro || !$token) {
2035
  throw new \NitroPack\SDK\WebhookException('Webhook token cannot be empty.');
2048
  function nitropack_disconnect() {
2049
  nitropack_uninstall_advanced_cache();
2050
  nitropack_event("disconnect");
2051
+ if (null !== $nitro = get_nitropack_sdk()) {
2052
+ nitropack_reset_webhooks($nitro);
2053
+ }
2054
  nitropack_unset_current_blog_config();
2055
  delete_option("nitropack-siteId");
2056
  delete_option("nitropack-siteSecret");
2076
  update_option("nitropack-autoCachePurge", (int)$autoCachePurgeStatus);
2077
  }
2078
 
2079
+ function nitropack_set_bb_cache_purge_sync_ajax() {
2080
+ $bbCacheSyncPurgeStatus = !empty($_POST["bbCachePurgeSyncStatus"]);
2081
+ update_option("nitropack-bbCacheSyncPurge", (int)$bbCacheSyncPurgeStatus);
2082
+ }
2083
+
2084
  function nitropack_set_cacheable_post_types() {
2085
  $currentCacheableObjectTypes = nitropack_get_cacheable_object_types();
2086
  $cacheableObjectTypes = !empty($_POST["cacheableObjectTypes"]) ? $_POST["cacheableObjectTypes"] : array();
2101
  function nitropack_test_compression_ajax() {
2102
  $hasCompression = true;
2103
  try {
2104
+ if (\NitroPack\Integration\Hosting\Flywheel::detect()) { // Flywheel: Compression is enabled by default
2105
  update_option("nitropack-enableCompression", 0);
2106
  } else {
2107
  require_once plugin_dir_path(__FILE__) . nitropack_trailingslashit('nitropack-sdk') . 'autoload.php';
2264
  } catch (\Exception $e) {
2265
  }
2266
 
2267
+ nitropack_cache_safemode_status(true);
2268
  nitropack_json_and_exit(array(
2269
  "type" => "success",
2270
  "message" => "Success! Safe mode has been enabled successfully!"
2284
  } catch (\Exception $e) {
2285
  }
2286
 
2287
+ nitropack_cache_safemode_status(false);
2288
  nitropack_json_and_exit(array(
2289
  "type" => "success",
2290
  "message" => "Success! Safe mode has been disabled successfully!"
2302
  try {
2303
  $isEnabled = $nitro->getApi()->isSafeModeEnabled();
2304
  } catch (\Exception $e) {
2305
+ nitropack_cache_safemode_status();
2306
  nitropack_json_and_exit(array(
2307
  "type" => "error",
2308
  "message" => "Error! There was an error while fetching the status of safe mode!"
2309
  ));
2310
  }
2311
 
2312
+ nitropack_cache_safemode_status($isEnabled);
2313
  nitropack_json_and_exit(array(
2314
  "type" => "success",
2315
  "isEnabled" => $isEnabled
2316
  ));
2317
  }
2318
 
2319
+ nitropack_cache_safemode_status();
2320
  nitropack_json_and_exit(array(
2321
  "type" => "error",
2322
  "message" => "Error! There was an error while fetching status of safe mode!"
2323
  ));
2324
  }
2325
 
2326
+ function nitropack_cache_safemode_status($operation = null) {
2327
+ $sm = "-1";
2328
+ if (is_bool($operation)) {
2329
+ $sm = $operation ? '1' : '0';
2330
+ }
2331
+ return update_option('nitropack-safeModeStatus', $sm);
2332
+ }
2333
+
2334
  function nitropack_data_dir_exists() {
2335
  return defined("NITROPACK_DATA_DIR") && is_dir(NITROPACK_DATA_DIR);
2336
  }
2412
  "admin_url" => $admin_url,
2413
  "hosting" => $hosting,
2414
  "alwaysBuffer" => $alwaysBuffer,
2415
+ "isEzoicActive" => \NitroPack\Integration\Plugin\Ezoic::isActive(),
2416
  "isLateIntegrationInitRequired" => nitropack_is_late_integration_init_required(),
2417
+ "isDlmActive" => \NitroPack\Integration\Plugin\DownloadManager::isActive(),
2418
+ "dlm_downloading_url" => \NitroPack\Integration\Plugin\DownloadManager::isActive() ? \NitroPack\Integration\Plugin\DownloadManager::downloadingUrl() : NULL,
2419
+ "dlm_download_endpoint" => \NitroPack\Integration\Plugin\DownloadManager::isActive() ? \NitroPack\Integration\Plugin\DownloadManager::downloadEndpoint() : NULL,
2420
  "pluginVersion" => NITROPACK_VERSION
2421
  );
2422
  return nitropack_set_config($staticConfig);
2469
  return $configFilePath;
2470
  }
2471
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2472
  function nitropack_detect_hosting() {
2473
+ if (\NitroPack\Integration\Hosting\Flywheel::detect()) {
2474
  return "flywheel";
2475
+ } else if (\NitroPack\Integration\Hosting\Cloudways::detect()) {
2476
  return "cloudways";
2477
+ } else if (\NitroPack\Integration\Hosting\WPEngine::detect()) {
2478
  return "wpengine";
2479
+ } else if (\NitroPack\Integration\Hosting\SiteGround::detect()) {
2480
  return "siteground";
2481
+ } else if (\NitroPack\Integration\Hosting\GoDaddyWPaaS::detect()) {
2482
  return "godaddy_wpaas";
2483
+ } else if (\NitroPack\Integration\Hosting\GridPane::detect()) {
2484
  return "gridpane";
2485
+ } else if (\NitroPack\Integration\Hosting\Kinsta::detect()) {
2486
  return "kinsta";
2487
+ } else if (\NitroPack\Integration\Hosting\Closte::detect()) {
2488
  return "closte";
2489
+ } else if (\NitroPack\Integration\Hosting\Pagely::detect()) {
2490
  return "pagely";
2491
  } else {
2492
  return "unknown";
2495
 
2496
  function nitropack_handle_request($servedFrom = "unknown") {
2497
  global $np_integrationSetupEvent;
2498
+
2499
  header('Cache-Control: no-cache');
2500
+ do_action("nitropack_early_cache_headers"); // Overrides the Cache-Control header on supported platforms
2501
  $isManageWpRequest = !empty($_GET["mwprid"]);
2502
  $isWpCli = nitropack_is_wp_cli();
2503
 
2525
  }
2526
  } else {
2527
  $GLOBALS["NitroPack.instance"] = $nitro;
2528
+
2529
+ if (nitropack_passes_cookie_requirements() || (nitropack_is_ajax() && !empty($_COOKIE["nitroCachedPage"])) ) {
2530
  // Check whether the current URL is cacheable
2531
  // 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.
2532
  // If we are not checking the referer, the AJAX requests on these pages can fail.
2534
  if ($nitro->isAllowedUrl($urlToCheck)) {
2535
  add_filter( 'nonce_life', 'nitropack_extend_nonce_life' );
2536
  }
2537
+ }
2538
 
2539
+ if (nitropack_passes_cookie_requirements()) {
2540
  if ($nitro->isCacheAllowed()) {
2541
+ if (!nitropack_is_ajax()) {
2542
+ do_action("nitropack_cacheable_cache_headers");
2543
+ }
2544
+
2545
  if (!empty($siteConfig["compression"])) {
2546
  $nitro->enableCompression();
2547
  }
2548
 
2549
  if ($nitro->hasLocalCache()) {
2550
+ // TODO: Make this work so we can provide the reverse proxies with this information $remainingTtl = $nitr->pageCache->getRemainingTtl();
2551
+ do_action("nitropack_cachehit_cache_headers"); // TODO: Pass the remaining TTL here
2552
  $cacheControlOverride = defined("NITROPACK_CACHE_CONTROL_OVERRIDE") ? NITROPACK_CACHE_CONTROL_OVERRIDE : NULL;
 
 
 
 
 
 
 
2553
  if ($cacheControlOverride) {
2554
  header('Cache-Control: ' . $cacheControlOverride);
2555
  }
2592
  return $siteConfig && empty($siteConfig["isEzoicActive"]);
2593
  }
2594
 
 
 
 
 
 
 
 
 
 
2595
  function nitropack_admin_bar_menu($wp_admin_bar){
2596
 
2597
 
2694
  wp_enqueue_style( 'nitropack_admin_bar_menu_stylesheet', plugin_dir_url(__FILE__) . 'view/stylesheet/admin_bar_menu.css?np_v=' . NITROPACK_VERSION);
2695
  }
2696
 
2697
+ function nitropack_cookiepath() {
2698
+ $siteConfig = nitropack_get_site_config();
2699
+ $homeUrl = $siteConfig && !empty($siteConfig["home_url"]) ? $siteConfig["home_url"] : get_home_url();
2700
+ $url = new \NitroPack\Url($homeUrl);
2701
+ return $url ? $url->getPath() : "/";
2702
+ }
2703
+
2704
+ function nitropack_setcookie($name, $value, $expires = NULL, $options = []) {
2705
+ $cookie_options = '';
2706
+ $cookie_path = nitropack_cookiepath();
2707
+
2708
+ if ($expires && is_numeric($expires)) {
2709
+ $options["Expires"] = date("D, d M Y H:i:s", (int)$expires) . ' GMT';
2710
+ }
2711
+
2712
+ if (empty($options["SameSite"])) {
2713
+ $options["SameSite"] = "Lax";
2714
+ }
2715
+
2716
+ foreach ($options as $optName => $optValue) {
2717
+ $cookie_options .= "$optName=$optValue; ";
2718
+ }
2719
+ header("set-cookie: $name=$value; Path=$cookie_path; " . $cookie_options, false);
2720
+ }
2721
+
2722
+ function nitropack_upgrade_handler($entity) {
2723
+ $np = 'nitropack/main.php';
2724
+ $trigger = $entity;
2725
+ if ($entity instanceof Plugin_Upgrader) {
2726
+ $trigger = $entity->plugin_info();
2727
+ if (!is_plugin_active($trigger)) {
2728
+ return;
2729
+ }
2730
+ }
2731
+
2732
+ if ($entity instanceof Theme_Upgrader) {
2733
+ if ($entity->theme_info()->Name === wp_get_theme()->Name) {
2734
+ nitropack_theme_handler('Theme updated');
2735
+ }
2736
+ return;
2737
+ }
2738
+
2739
+ if ($trigger !== $np) {
2740
+ $cookie_expires = date("D, d M Y H:i:s",time() + 600) . ' GMT';
2741
+ nitropack_setcookie('nitropack_apwarning', "1", time() + 600);
2742
+ }
2743
+ }
2744
+
2745
  function nitropack_plugin_notices() {
2746
  static $npPluginNotices = NULL;
2747
 
2753
  $warnings = [];
2754
  $infos = [];
2755
 
2756
+ // Add conficting plugins errors
2757
  $conflictingPlugins = nitropack_get_conflicting_plugins();
2758
  foreach ($conflictingPlugins as $clashingPlugin) {
2759
  $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);
2760
  }
2761
 
2762
+ // Add residual cache notices if found
2763
+ $residualCachePlugins = \NitroPack\Integration\Plugin\RC::detectThirdPartyCaches();
2764
+ foreach ($residualCachePlugins as $rcpName) {
2765
+ $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);
2766
+ }
2767
+
2768
+ // Add plugins state notices
2769
+ if (isset($_COOKIE['nitropack_apwarning'])) {
2770
+ $cookie_path = nitropack_cookiepath();
2771
+ $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>";
2772
+ }
2773
+
2774
  $nitropackIsConnected = nitropack_is_connected();
2775
 
2776
  if ($nitropackIsConnected) {
2804
  }
2805
 
2806
  if ( (!defined("WP_CACHE") || !WP_CACHE) ) {
2807
+ if (\NitroPack\Integration\Hosting\Flywheel::detect()) { // Flywheel: This is configured throught the FW control panel
2808
  $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>.";
2809
  } else if (!nitropack_set_wp_cache_const(true)) {
2810
  $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.";
2855
  }
2856
  } else {
2857
  if (
2858
+ (!array_key_exists("isEzoicActive", $siteConfig) || $siteConfig["isEzoicActive"] !== \NitroPack\Integration\Plugin\Ezoic::isActive()) ||
2859
  (!array_key_exists("isLateIntegrationInitRequired", $siteConfig) || $siteConfig["isLateIntegrationInitRequired"] !== nitropack_is_late_integration_init_required()) ||
2860
+ (!array_key_exists("isDlmActive", $siteConfig) || $siteConfig["isDlmActive"] !== \NitroPack\Integration\Plugin\DownloadManager::isActive())
2861
  ) {
2862
  if (!nitropack_update_current_blog_config($siteId, $siteSecret, $blogId)) {
2863
  $errors[] = "The NitroPack static config file cannot be updated. Please make sure that the /wp-content/nitropack/ directory is writable and refresh this page.";
2868
  if (null !== $nitro = get_nitropack_sdk() ) {
2869
  try {
2870
  if (!headers_sent()) {
2871
+ nitropack_setcookie("nitropack_webhook_sync", "1", time() + 300); // Do these checks in 5 minute intervals.
2872
  }
2873
  $configWebhook = $nitro->getApi()->getWebhook("config");
2874
  if (!empty($configWebhook)) {
2902
  }
2903
 
2904
  function nitropack_is_late_integration_init_required() {
2905
+ return \NitroPack\Integration\Plugin\NginxHelper::isActive() || \NitroPack\Integration\Plugin\Cloudflare::isApoActive();
2906
  }
2907
 
2908
  function nitropack_display_admin_notices() {
2929
  }
2930
  }
2931
 
2932
+ function nitropack_offer_safemode() {
2933
+ global $pagenow;
2934
+ if ($pagenow == 'plugins.php') {
2935
+ $smStatus = get_option('nitropack-safeModeStatus', "-1");
2936
+ if ($smStatus === "0") {
2937
+ add_action('admin_enqueue_scripts', function() {
2938
+ wp_enqueue_script( 'np_safemode', plugin_dir_url( __FILE__ ). 'view/javascript/np_safemode.js', array('jquery'));
2939
+ wp_enqueue_style('np_safemode', plugin_dir_url( __FILE__ ) . 'view/stylesheet/np_safemode.css');
2940
+ });
2941
+ add_action('admin_footer', function(){require_once NITROPACK_PLUGIN_DIR . 'view/safemode.tpl';});
2942
+ }
2943
+ }
2944
+ }
2945
+
2946
  // Init integration action handlers
2947
  require_once 'integrations.php';
 
 
 
 
 
 
integrations.php CHANGED
@@ -1,405 +1,17 @@
1
  <?php
2
 
3
- if (nitropack_is_wpe()) {
4
- define("NITROPACK_USE_MICROTIMEOUT", 20000);
5
- }
6
-
7
- function nitropack_check_and_init_integrations() {
8
- $siteConfig = nitropack_get_site_config();
9
- if ($siteConfig && !empty($siteConfig["hosting"])) {
10
- $hosting = $siteConfig["hosting"];
11
- } else {
12
- $hosting = nitropack_detect_hosting();
13
- }
14
-
15
- switch ($hosting) {
16
- case "cloudways":
17
- add_action('nitropack_integration_purge_url', 'nitropack_cloudways_purge_url');
18
- add_action('nitropack_integration_purge_all', 'nitropack_cloudways_purge_all');
19
- break;
20
- case "flywheel":
21
- add_filter('nitropack_varnish_purger', 'nitropack_flywheel_varnish_instance');
22
- add_action('nitropack_integration_purge_url', 'nitropack_varnish_purge_url');
23
- add_action('nitropack_integration_purge_all', 'nitropack_varnish_purge_all');
24
- break;
25
- case "wpengine":
26
- add_action('nitropack_integration_purge_url', 'nitropack_wpe_purge_url');
27
- add_action('nitropack_integration_purge_all', 'nitropack_wpe_purge_all');
28
- break;
29
- case "siteground":
30
- add_action('nitropack_integration_purge_url', 'nitropack_siteground_purge_url');
31
- add_action('nitropack_integration_purge_all', 'nitropack_siteground_purge_all');
32
- break;
33
- case "godaddy_wpaas":
34
- add_action('nitropack_integration_purge_url', 'nitropack_wpaas_purge_url');
35
- add_action('nitropack_integration_purge_all', 'nitropack_wpaas_purge_all');
36
- break;
37
- case "kinsta":
38
- add_action('nitropack_integration_purge_url', 'nitropack_kinsta_purge_url');
39
- add_action('nitropack_integration_purge_all', 'nitropack_kinsta_purge_all');
40
- break;
41
- case "pagely":
42
- add_action('nitropack_integration_purge_url', 'nitropack_pagely_purge_url');
43
- add_action('nitropack_integration_purge_all', 'nitropack_pagely_purge_all');
44
- break;
45
- default:
46
- break;
47
- }
48
-
49
- if ($siteConfig && empty($siteConfig["isLateIntegrationInitRequired"])) {
50
- do_action(NITROPACK_INTEGRATIONS_ACTION);
51
- }
52
-
53
- // This is needed in order to load non-cache-related integrations like the one with ShortPixel and WooCommerce Geo Location.
54
- if (did_action('plugins_loaded')) {
55
- nitropack_init_late_integrations();
56
- } else {
57
- add_action('plugins_loaded', 'nitropack_init_late_integrations');
58
- }
59
- }
60
-
61
- function nitropack_init_late_integrations() {
62
- if (defined("NITROPACK_LATE_INTEGRATIONS")) return;
63
- define("NITROPACK_LATE_INTEGRATIONS", true);
64
-
65
- // Cache related integrations
66
- if (nitropack_is_nginx_helper_active()) {
67
- add_action('nitropack_integration_purge_url', 'nitropack_nginx_helper_purge_url');
68
- add_action('nitropack_integration_purge_all', 'nitropack_nginx_helper_purge_all');
69
- }
70
-
71
- if (nitropack_is_apo_active()) {
72
- add_action('nitropack_integration_purge_url', 'nitropack_apo_purge_url');
73
- add_action('nitropack_integration_purge_all', 'nitropack_apo_purge_all');
74
- }
75
-
76
- // Non cache related integrations
77
- if (defined('SHORTPIXEL_AI_VERSION')) { // ShortPixel
78
- if (nitropack_is_ajax()) {
79
- if (version_compare(SHORTPIXEL_AI_VERSION, "2", ">=")) { // ShortPixel AI 2.x
80
- remove_action('wp_enqueue_scripts', array(ShortPixelAI::_(), 'enqueue_script'));
81
- remove_action('init', array(ShortPixelAI::_(), 'init_ob'), 1);
82
- remove_filter('script_loader_tag', array(ShortPixelAI::_(), 'disable_rocket-Loader'), 10);
83
- } else { // ShortPixel AI 1.x
84
- remove_action('wp_enqueue_scripts', array(ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'enqueue_script'), 11);
85
- remove_action('init', array(ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'init_ob'), 1);
86
- remove_filter('rocket_css_content', array(ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'parse_cached_css'), 10);
87
- remove_filter('script_loader_tag', array(ShortPixelAI::instance(SHORTPIXEL_AI_PLUGIN_FILE), 'disable_rocket-Loader'), 10);
88
- }
89
- }
90
- }
91
-
92
- if (class_exists("WC_Cache_Helper")) {
93
- remove_action('template_redirect', array('WC_Cache_Helper', 'geolocation_ajax_redirect'));
94
- }
95
-
96
- $siteConfig = nitropack_get_site_config();
97
- if ($siteConfig && !empty($siteConfig["isLateIntegrationInitRequired"])) {
98
- do_action(NITROPACK_INTEGRATIONS_ACTION);
99
- }
100
- }
101
-
102
- /** WP Engine **/
103
- function nitropack_wpe_purge_url($url) {
104
- try {
105
- $handler = function($paths) use($url) {
106
- $wpe_path = parse_url($url, PHP_URL_PATH);
107
- $wpe_query = parse_url($url, PHP_URL_QUERY);
108
- $varnish_path = $wpe_path;
109
- if (!empty($wpe_query)) {
110
- $varnish_path .= '?' . $wpe_query;
111
- }
112
- if ($url && count($paths) == 1 && $paths[0] == ".*") {
113
- return array($varnish_path);
114
- }
115
- return $paths;
116
- };
117
- add_filter( 'wpe_purge_varnish_cache_paths', $handler );
118
- if (class_exists("WpeCommon")) { // We need to have this check for clients that switch hosts
119
- WpeCommon::purge_varnish_cache();
120
- }
121
- remove_filter( 'wpe_purge_varnish_cache_paths', $handler );
122
- } catch (\Exception $e) {
123
- // WPE exception
124
- }
125
- }
126
-
127
- function nitropack_wpe_purge_all() {
128
- try {
129
- if (class_exists("WpeCommon")) { // We need to have this check for clients that switch hosts
130
- WpeCommon::purge_varnish_cache();
131
- }
132
- } catch (\Exception $e) {
133
- // WPE exception
134
- }
135
- }
136
-
137
- /** Cloudways' Breeze plugin **/
138
- function nitropack_cloudways_purge_url($url) {
139
- try {
140
- $purger = new \NitroPack\SDK\Integrations\Varnish(array("127.0.0.1"), "URLPURGE");
141
- $purger->purge($url);
142
- } catch (\Exception $e) {
143
- // Breeze exception
144
- }
145
- }
146
-
147
- function nitropack_cloudways_purge_all() {
148
- try {
149
- $homepage = home_url().'/.*';
150
- $purger = new \NitroPack\SDK\Integrations\Varnish(array("127.0.0.1"), "PURGE");
151
- $purger->purge($homepage);
152
- } catch (\Exception $e) {
153
- // Exception
154
- }
155
- }
156
-
157
- /** SiteGround - Even though they use Nginx we can communicate with it as if it was Varnish **/
158
- function nitropack_siteground_purge_url($url) {
159
- $url = preg_replace("/^https?:\/\//", "", $url);
160
- $url = preg_replace("/^www\./", "", $url);
161
- $url = "http://" . $url;
162
-
163
- try {
164
- $hosts = ['127.0.0.1'];
165
- $purger = new \NitroPack\SDK\Integrations\Varnish($hosts, 'PURGE');
166
- $purger->purge($url);
167
- } catch (\Exception $e) {}
168
-
169
- return true;
170
- }
171
-
172
- function nitropack_siteground_purge_all() {
173
- $siteConfig = nitropack_get_site_config();
174
- if ($siteConfig && !empty($siteConfig["home_url"])) {
175
- return nitropack_siteground_purge_url($siteConfig["home_url"]);
176
- }
177
- return false;
178
- }
179
-
180
- /** GoDaddy WPaaS - Even though they use ApacheTrafficServer we can communicate with it as if it was Varnish **/
181
- function nitropack_wpaas_purge_url($url) {
182
- if (class_exists('\WPaaS\Plugin')) {
183
- update_option( 'gd_system_last_cache_flush', time() );
184
- $hosts = [\WPaaS\Plugin::vip()];
185
- $url = preg_replace("/^https:\/\//", "http://", $url);
186
- $purger = new \NitroPack\SDK\Integrations\Varnish($hosts, 'BAN');
187
- $purger->purge($url);
188
- return true;
189
- }
190
-
191
- return false;
192
- }
193
-
194
- function nitropack_wpaas_purge_all() {
195
- $siteConfig = nitropack_get_site_config();
196
- if ($siteConfig && !empty($siteConfig["home_url"])) {
197
- return nitropack_wpaas_purge_url($siteConfig["home_url"]);
198
- }
199
- return false;
200
- }
201
-
202
- /** Kinsta **/
203
- function nitropack_kinsta_purge_url($url) {
204
- try {
205
- $data = array(
206
- 'single|nitropack' => preg_replace( '@^https?://@', '', $url)
207
- );
208
- $httpClient = new \NitroPack\HttpClient("https://localhost/kinsta-clear-cache/v2/immediate");
209
- $httpClient->setPostData($data);
210
- $httpClient->fetch(true, "POST");
211
- return true;
212
- } catch (\Exception $e) {
213
- }
214
-
215
- return false;
216
- }
217
-
218
- function nitropack_kinsta_purge_all() {
219
- try {
220
- $httpClient = new \NitroPack\HttpClient("https://localhost/kinsta-clear-cache-all");
221
- $httpClient->timeout = 5;
222
- $httpClient->fetch();
223
- return true;
224
- } catch (\Exception $e) {
225
  }
 
226
 
227
- return false;
228
- }
229
-
230
- /** Flywheel Varnish **/
231
- function nitropack_flywheel_varnish_instance($type) {
232
- return new \NitroPack\SDK\Integrations\Varnish(array('127.0.0.1'), 'PURGE');
233
- }
234
-
235
- /** Generic Varnish **/
236
- function nitropack_varnish_generic_instance($type) {
237
- $varnishConfig = nitropack_get_varnish_settings();
238
- $purgeMethod = ($type == 'single') ? $varnishConfig->PurgeSingleMethod : $varnishConfig->PurgeAllMethod;
239
- if (empty($purgeMethod)) $purgeMethod = 'PURGE';
240
- return new \NitroPack\SDK\Integrations\Varnish($varnishConfig->Servers, $purgeMethod);
241
- }
242
-
243
- function nitropack_varnish_purge_url($url) {
244
- try {
245
- $purger = apply_filters('nitropack_varnish_purger', 'single');
246
- $purger->purge($url);
247
- } catch (\Exception $e) {
248
- // Exception encountered while trying to purge varnish cache
249
- }
250
- }
251
-
252
- function nitropack_varnish_purge_all() {
253
- try {
254
- $purger = apply_filters('nitropack_varnish_purger', 'all');
255
- if (function_exists("get_home_url")) {
256
- $home = get_home_url();
257
- } else {
258
- $siteConfig = nitropack_get_site_config();
259
- $home = "/";
260
- if ($siteConfig && !empty($siteConfig["home_url"])) {
261
- $home = $siteConfig["home_url"];
262
- }
263
- }
264
- $purger->purge($home);
265
- } catch (\Exception $e) {
266
- // Exception encountered while trying to purge varnish cache
267
- }
268
- }
269
-
270
- function nitropack_get_varnish_settings() {
271
- if (null !== $nitro = get_nitropack_sdk()) {
272
- $config = $nitro->getConfig();
273
- return !empty($config->CacheIntegrations) && $empty($config->CacheIntegrations->Varnish) ? $config->CacheIntegrations->Varnish : null;
274
- }
275
-
276
- return null;
277
- }
278
-
279
- // Nginx Helper integration
280
- function nitropack_is_nginx_helper_active() {
281
- return defined('NGINX_HELPER_BASEPATH');
282
- }
283
-
284
- function nitropack_nginx_helper_purge_url($url) {
285
- global $nginx_purger;
286
- if ($nginx_purger) {
287
- $nginx_purger->purge_url($url);
288
- }
289
- return true;
290
- }
291
-
292
- function nitropack_nginx_helper_purge_all() {
293
- global $nginx_purger;
294
- if ($nginx_purger) {
295
- $nginx_purger->purge_all();
296
- }
297
- return true;
298
- }
299
-
300
- // Cloudflare APO integration
301
- function nitropack_is_apo_active() {
302
- if (defined('CLOUDFLARE_PLUGIN_DIR')) {
303
- require_once NITROPACK_PLUGIN_DIR . 'cf-helper.php';
304
- $cfHelper = new NitroPack_CF_Helper();
305
- return $cfHelper->isApoEnabled();
306
- } else {
307
- return false;
308
- }
309
- }
310
-
311
- function nitropack_apo_purge_url($url) {
312
- if (defined('CLOUDFLARE_PLUGIN_DIR')) {
313
- require_once NITROPACK_PLUGIN_DIR . 'cf-helper.php';
314
- $cfHelper = new NitroPack_CF_Helper();
315
- return $cfHelper->purgeUrl($url);
316
- } else {
317
- return false;
318
- }
319
- }
320
-
321
- function nitropack_apo_purge_all() {
322
- if (defined('CLOUDFLARE_PLUGIN_DIR')) {
323
- require_once NITROPACK_PLUGIN_DIR . 'cf-helper.php';
324
- $cfHelper = new NitroPack_CF_Helper();
325
- return $cfHelper->purgeCacheEverything();
326
- } else {
327
- return false;
328
- }
329
- }
330
-
331
- /** Pagely **/
332
- function nitropack_pagely_purge_url($url) {
333
- try {
334
- $path = parse_url($url, PHP_URL_PATH);
335
- if (class_exists("PagelyCachePurge")) { // We need to have this check for clients that switch hosts
336
- $pagely = new \PagelyCachePurge();
337
- $pagely->purgePath($path . "(.*)");
338
- }
339
- } catch (\Exception $e) {
340
- // Pagely exception
341
- }
342
- }
343
-
344
- function nitropack_pagely_purge_all() {
345
- try {
346
- if (class_exists("PagelyCachePurge")) { // We need to have this check for clients that switch hosts
347
- $pagely = new \PagelyCachePurge();
348
- $pagely->purgeAll();
349
- }
350
- } catch (\Exception $e) {
351
- // Pagely exception
352
- }
353
- }
354
-
355
- // Ezoic integration
356
- function nitropack_is_ezoic_active() {
357
- return defined('EZOIC_INTEGRATION_VERSION');
358
- }
359
-
360
- function nitropack_disable_ezoic() {
361
- global $wp_filter;
362
- $hook = "shutdown";
363
-
364
- if ( isset( $wp_filter[$hook]->callbacks ) ) {
365
- array_walk( $wp_filter[$hook]->callbacks, function( $callbacks, $priority ) use ( &$hooks ) {
366
- foreach ( $callbacks as $id => $callback ) {
367
- $cb = $callback["function"];
368
- if (is_callable($cb) && is_array($cb) && $cb[1] == "ez_buffer_end") {
369
- remove_filter("shutdown", $cb, $priority);
370
- register_shutdown_function('ob_end_flush');
371
- }
372
- }
373
- });
374
- }
375
- }
376
-
377
- function nitropack_ezoic_home_url($url) {
378
- $siteConfig = nitropack_get_site_config();
379
- if ( $siteConfig && null !== $nitro = get_nitropack_sdk($siteConfig["siteId"], $siteConfig["siteSecret"]) ) {
380
- $nitroUrl = $nitro->getUrl();
381
- $queryStart = strpos($nitroUrl, "?");
382
- if ($queryStart !== false) {
383
- return substr($nitroUrl, 0, $queryStart);
384
- } else {
385
- return $nitroUrl;
386
- }
387
- }
388
-
389
- return $url;
390
- }
391
-
392
- // Download Manager integration
393
- function nitropack_is_dlm_active() {
394
- return defined('DLM_VERSION');
395
- }
396
-
397
- function nitropack_dlm_downloading_url() {
398
- $downloadingPage = get_option("dlm_dp_downloading_page");
399
- return $downloadingPage ? get_permalink($downloadingPage) : NULL;
400
  }
401
 
402
- function nitropack_dlm_download_endpoint() {
403
- $downloadEndpoint = get_option("dlm_download_endpoint");
404
- return $downloadEndpoint ? nitropack_trailingslashit(get_home_url()) . $downloadEndpoint : NULL;
405
- }
1
  <?php
2
 
3
+ spl_autoload_register(function($class) {
4
+ $filename = str_replace("\\", "/", $class) . ".php";
5
+ $filename = str_replace("NitroPack/", "", $filename);
6
+ $filepath = NITROPACK_CLASSES_DIR . ltrim($filename, "/");
7
+ if (file_exists($filepath)) {
8
+ require_once $filepath;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
10
+ });
11
 
12
+ if (\NitroPack\Integration\Hosting\WPEngine::detect()) {
13
+ define("NITROPACK_USE_MICROTIMEOUT", 20000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  }
15
 
16
+ $integration = NitroPack\Integration::getInstance();
17
+ $integration->init();
 
 
main.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: NitroPack
4
  Plugin URI: https://nitropack.io/platform/wordpress
5
  Description: Everything you need for a fast website. Simple set up, easy to use, awesome support. Caching, Lazy Loading, Minification, Defer CSS/JS, CDN and more!
6
- Version: 1.5.4
7
  Author: NitroPack LLC
8
  Author URI: https://nitropack.io/
9
  License: GPL2
@@ -19,16 +19,16 @@ if (nitropack_is_wp_cli()) {
19
  require_once $np_basePath . 'wp-cli.php';
20
  }
21
 
22
- if ( nitropack_is_ezoic_active() ) {
23
  if (!nitropack_is_optimizer_request()) {
24
  // We need to serve the cached content after Ezoic's output buffering has started at plugins_loaded,0
25
  add_action( 'plugins_loaded', function() {
26
- add_filter( 'home_url', 'nitropack_ezoic_home_url' );
27
  nitropack_handle_request("plugin-ezoic");
28
- remove_filter( 'home_url', 'nitropack_ezoic_home_url' );
29
  }, 1 );
30
  } else {
31
- add_action( 'plugins_loaded', 'nitropack_disable_ezoic', 1);
32
  }
33
  } else {
34
  nitropack_handle_request("plugin");
@@ -38,13 +38,12 @@ add_action( 'pre_post_update', 'nitropack_log_post_pre_update', 10, 3);
38
  add_action( 'transition_post_status', 'nitropack_handle_post_transition', 10, 3);
39
  add_action( 'transition_comment_status', 'nitropack_handle_comment_transition', 10, 3);
40
  add_action( 'comment_post', 'nitropack_handle_comment_post', 10, 2);
41
- add_action( 'switch_theme', 'nitropack_switch_theme' );
42
  add_action( 'shutdown', 'nitropack_execute_purges', -1000 );
43
  add_action( 'shutdown', 'nitropack_execute_invalidations', -1000 );
44
  add_action( 'shutdown', 'nitropack_execute_warmups', -1000 );
45
 
46
- add_action( 'woocommerce_updated_product_stock', 'nitropack_handle_product_stock_updates', 0, 1);
47
- add_action( 'woocommerce_updated_product_price', 'nitropack_handle_product_price_updates', 0, 1);
48
  add_action( 'woocommerce_rest_insert_product', function($post, $request, $creating) {
49
  if (!$creating) {
50
  nitropack_clean_post_cache($post);
@@ -79,11 +78,13 @@ if ( is_admin() ) {
79
  add_action( 'network_admin_notices', 'nitropack_admin_notices' );
80
  add_action( 'wp_ajax_nitropack_purge_cache', 'nitropack_purge_cache' );
81
  add_action( 'wp_ajax_nitropack_invalidate_cache', 'nitropack_invalidate_cache' );
 
82
  add_action( 'wp_ajax_nitropack_verify_connect', 'nitropack_verify_connect_ajax' );
83
  add_action( 'wp_ajax_nitropack_disconnect', 'nitropack_disconnect' );
84
  add_action( 'wp_ajax_nitropack_test_compression_ajax', 'nitropack_test_compression_ajax' );
85
  add_action( 'wp_ajax_nitropack_set_compression_ajax', 'nitropack_set_compression_ajax' );
86
  add_action( 'wp_ajax_nitropack_set_auto_cache_purge_ajax', 'nitropack_set_auto_cache_purge_ajax' );
 
87
  add_action( 'wp_ajax_nitropack_set_cacheable_post_types', 'nitropack_set_cacheable_post_types' );
88
  add_action( 'wp_ajax_nitropack_enable_warmup', 'nitropack_enable_warmup' );
89
  add_action( 'wp_ajax_nitropack_disable_warmup', 'nitropack_disable_warmup' );
@@ -93,13 +94,18 @@ if ( is_admin() ) {
93
  add_action( 'wp_ajax_nitropack_purge_single_cache', 'nitropack_purge_single_cache' );
94
  add_action( 'wp_ajax_nitropack_invalidate_single_cache', 'nitropack_invalidate_single_cache' );
95
  add_action( 'wp_ajax_nitropack_dismiss_hosting_notice', 'nitropack_dismiss_hosting_notice' );
 
96
  add_action( 'wp_ajax_nitropack_reconfigure_webhooks', 'nitropack_reconfigure_webhooks' );
97
  add_action( 'wp_ajax_nitropack_generate_report', 'nitropack_generate_report' );//diag_ajax_hook
98
  add_action( 'wp_ajax_nitropack_enable_safemode', 'nitropack_enable_safemode' );
99
  add_action( 'wp_ajax_nitropack_disable_safemode', 'nitropack_disable_safemode' );
100
  add_action( 'wp_ajax_nitropack_safemode_status', 'nitropack_safemode_status' );
 
 
 
101
  add_action( 'update_option_nitropack-enableCompression', 'nitropack_handle_compression_toggle', 10, 2 );
102
  add_action( 'add_meta_boxes', 'nitropack_add_meta_box' );
 
103
 
104
  register_activation_hook( __FILE__, 'nitropack_activate' );
105
  register_deactivation_hook( __FILE__, 'nitropack_deactivate' );
3
  Plugin Name: NitroPack
4
  Plugin URI: https://nitropack.io/platform/wordpress
5
  Description: Everything you need for a fast website. Simple set up, easy to use, awesome support. Caching, Lazy Loading, Minification, Defer CSS/JS, CDN and more!
6
+ Version: 1.5.5
7
  Author: NitroPack LLC
8
  Author URI: https://nitropack.io/
9
  License: GPL2
19
  require_once $np_basePath . 'wp-cli.php';
20
  }
21
 
22
+ if ( \NitroPack\Integration\Plugin\Ezoic::isActive() ) {
23
  if (!nitropack_is_optimizer_request()) {
24
  // We need to serve the cached content after Ezoic's output buffering has started at plugins_loaded,0
25
  add_action( 'plugins_loaded', function() {
26
+ add_filter( 'home_url', ['\NitroPack\Integration\Plugin\Ezoic', 'getHomeUrl'] );
27
  nitropack_handle_request("plugin-ezoic");
28
+ remove_filter( 'home_url', ['\NitroPack\Integration\Plugin\Ezoic', 'getHomeUrl'] );
29
  }, 1 );
30
  } else {
31
+ add_action( 'plugins_loaded', ['\NitroPack\Integration\Plugin\Ezoic', 'disable'], 1);
32
  }
33
  } else {
34
  nitropack_handle_request("plugin");
38
  add_action( 'transition_post_status', 'nitropack_handle_post_transition', 10, 3);
39
  add_action( 'transition_comment_status', 'nitropack_handle_comment_transition', 10, 3);
40
  add_action( 'comment_post', 'nitropack_handle_comment_post', 10, 2);
41
+ add_action( 'switch_theme', 'nitropack_theme_handler' );
42
  add_action( 'shutdown', 'nitropack_execute_purges', -1000 );
43
  add_action( 'shutdown', 'nitropack_execute_invalidations', -1000 );
44
  add_action( 'shutdown', 'nitropack_execute_warmups', -1000 );
45
 
46
+ add_action( 'woocommerce_product_object_updated_props', 'nitropack_handle_product_updates', 0, 2);
 
47
  add_action( 'woocommerce_rest_insert_product', function($post, $request, $creating) {
48
  if (!$creating) {
49
  nitropack_clean_post_cache($post);
78
  add_action( 'network_admin_notices', 'nitropack_admin_notices' );
79
  add_action( 'wp_ajax_nitropack_purge_cache', 'nitropack_purge_cache' );
80
  add_action( 'wp_ajax_nitropack_invalidate_cache', 'nitropack_invalidate_cache' );
81
+ add_action( 'wp_ajax_nitropack_clear_residual_cache', 'nitropack_clear_residual_cache' );
82
  add_action( 'wp_ajax_nitropack_verify_connect', 'nitropack_verify_connect_ajax' );
83
  add_action( 'wp_ajax_nitropack_disconnect', 'nitropack_disconnect' );
84
  add_action( 'wp_ajax_nitropack_test_compression_ajax', 'nitropack_test_compression_ajax' );
85
  add_action( 'wp_ajax_nitropack_set_compression_ajax', 'nitropack_set_compression_ajax' );
86
  add_action( 'wp_ajax_nitropack_set_auto_cache_purge_ajax', 'nitropack_set_auto_cache_purge_ajax' );
87
+ add_action( 'wp_ajax_nitropack_set_bb_cache_purge_sync_ajax', 'nitropack_set_bb_cache_purge_sync_ajax' );
88
  add_action( 'wp_ajax_nitropack_set_cacheable_post_types', 'nitropack_set_cacheable_post_types' );
89
  add_action( 'wp_ajax_nitropack_enable_warmup', 'nitropack_enable_warmup' );
90
  add_action( 'wp_ajax_nitropack_disable_warmup', 'nitropack_disable_warmup' );
94
  add_action( 'wp_ajax_nitropack_purge_single_cache', 'nitropack_purge_single_cache' );
95
  add_action( 'wp_ajax_nitropack_invalidate_single_cache', 'nitropack_invalidate_single_cache' );
96
  add_action( 'wp_ajax_nitropack_dismiss_hosting_notice', 'nitropack_dismiss_hosting_notice' );
97
+ add_action( 'wp_ajax_nitropack_dismiss_woocommerce_notice', 'nitropack_dismiss_woocommerce_notice' );
98
  add_action( 'wp_ajax_nitropack_reconfigure_webhooks', 'nitropack_reconfigure_webhooks' );
99
  add_action( 'wp_ajax_nitropack_generate_report', 'nitropack_generate_report' );//diag_ajax_hook
100
  add_action( 'wp_ajax_nitropack_enable_safemode', 'nitropack_enable_safemode' );
101
  add_action( 'wp_ajax_nitropack_disable_safemode', 'nitropack_disable_safemode' );
102
  add_action( 'wp_ajax_nitropack_safemode_status', 'nitropack_safemode_status' );
103
+ add_action( 'activated_plugin', 'nitropack_upgrade_handler' );
104
+ add_action( 'deactivated_plugin', 'nitropack_upgrade_handler' );
105
+ add_action( 'upgrader_process_complete', 'nitropack_upgrade_handler');
106
  add_action( 'update_option_nitropack-enableCompression', 'nitropack_handle_compression_toggle', 10, 2 );
107
  add_action( 'add_meta_boxes', 'nitropack_add_meta_box' );
108
+ add_action( 'plugins_loaded', 'nitropack_offer_safemode');
109
 
110
  register_activation_hook( __FILE__, 'nitropack_activate' );
111
  register_deactivation_hook( __FILE__, 'nitropack_deactivate' );
nitropack-sdk/NitroPack/SDK/Filesystem.php CHANGED
@@ -63,8 +63,8 @@ class Filesystem {
63
  return self::fileExists($filePath) ? Filesystem::getStorageDriver()->mtime($filePath) : 0;
64
  }
65
 
66
- public static function touch($filePath) {
67
- return Filesystem::getStorageDriver()->touch($filePath);
68
  }
69
 
70
  public static function fileGetHeaders($filePath) {
@@ -98,9 +98,7 @@ class Filesystem {
98
  }
99
 
100
  public static function filePutContents($file, $content, $headers = NULL) {
101
- if ($headers === NULL) {
102
- return Filesystem::getStorageDriver()->setContent($file, $content);
103
- } else if (is_array($headers)) {
104
  $headerStr = implode("\r\n", $headers) . "\r\n\r\n";
105
  return Filesystem::getStorageDriver()->setContent($file, $headerStr . $content);
106
  } else if (is_string($headers)) {
@@ -162,7 +160,7 @@ class Filesystem {
162
  return Filesystem::getStorageDriver()->feof($fh);
163
  }
164
 
165
- private static function explodeByHeaders($content) {
166
  $headers = [];
167
  $pos = strpos($content, "\r\n\r\n");
168
  if ($pos !== false) {
63
  return self::fileExists($filePath) ? Filesystem::getStorageDriver()->mtime($filePath) : 0;
64
  }
65
 
66
+ public static function touch($filePath, $time = NULL) {
67
+ return Filesystem::getStorageDriver()->touch($filePath, $time);
68
  }
69
 
70
  public static function fileGetHeaders($filePath) {
98
  }
99
 
100
  public static function filePutContents($file, $content, $headers = NULL) {
101
+ if (is_array($headers)) {
 
 
102
  $headerStr = implode("\r\n", $headers) . "\r\n\r\n";
103
  return Filesystem::getStorageDriver()->setContent($file, $headerStr . $content);
104
  } else if (is_string($headers)) {
160
  return Filesystem::getStorageDriver()->feof($fh);
161
  }
162
 
163
+ public static function explodeByHeaders($content) {
164
  $headers = [];
165
  $pos = strpos($content, "\r\n\r\n");
166
  if ($pos !== false) {
nitropack-sdk/NitroPack/SDK/NitroPack.php CHANGED
@@ -2,7 +2,7 @@
2
  namespace NitroPack\SDK;
3
 
4
  class NitroPack {
5
- const VERSION = '0.20.0';
6
  const PAGECACHE_LOCK_EXPIRATION_TIME = 300; // in seconds
7
  private $dataDir;
8
  private $cachePath = array('data', 'pagecache');
@@ -83,6 +83,18 @@ class NitroPack {
83
  return implode(".*?", array_map(function($input) use ($delim) { return preg_quote($input, $delim); }, explode("*", $str)));
84
  }
85
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  public function __construct($siteId, $siteSecret, $userAgent = NULL, $url = NULL, $dataDir = __DIR__) {
87
  $this->configTTL = 3600;
88
  $this->siteId = $siteId;
@@ -110,7 +122,7 @@ class NitroPack {
110
  $queryStr = parse_url($url, PHP_URL_QUERY);
111
 
112
  if ($queryStr) {
113
- parse_str($queryStr, $queryParams);
114
 
115
  if ($queryParams) {
116
  if ($this->config->IgnoredParams) {
@@ -287,7 +299,8 @@ class NitroPack {
287
  $this->pageCache->useInvalidated(false);
288
  // End of check
289
 
290
- $this->pageCache->setContent($resp->getBody());
 
291
  return true;
292
  } else {
293
  // The goal is to serve cache at all times even when it is slightly outdated. This approach should be ok because new cache has been requested and it should be ready soon
@@ -584,10 +597,17 @@ class NitroPack {
584
  }
585
 
586
  public function isSecure() {
587
- return (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && in_array("https", array_map("strtolower", array_map("trim", explode(",", $_SERVER['HTTP_X_FORWARDED_PROTO']))))) ||
588
  (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
589
  (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) ||
590
  (!empty($_SERVER['HTTP_SSL_FLAG']) && $_SERVER['HTTP_SSL_FLAG'] == 'SSL');
 
 
 
 
 
 
 
591
  }
592
 
593
  public function isAJAXRequest() {
2
  namespace NitroPack\SDK;
3
 
4
  class NitroPack {
5
+ const VERSION = '0.30.0';
6
  const PAGECACHE_LOCK_EXPIRATION_TIME = 300; // in seconds
7
  private $dataDir;
8
  private $cachePath = array('data', 'pagecache');
83
  return implode(".*?", array_map(function($input) use ($delim) { return preg_quote($input, $delim); }, explode("*", $str)));
84
  }
85
 
86
+ private function nitro_parse_str($qStr, &$resArr) {
87
+ if (strpos($qStr, '?') !== false) {
88
+ $tmpArr = explode('?', $qStr, 2);
89
+ parse_str($tmpArr[0], $resArr);
90
+ $completeValue = end($resArr) . $tmpArr[1];
91
+ $resArr[key($resArr)] = $completeValue;
92
+ reset($resArr);
93
+ } else {
94
+ parse_str($qStr, $resArr);
95
+ }
96
+ }
97
+
98
  public function __construct($siteId, $siteSecret, $userAgent = NULL, $url = NULL, $dataDir = __DIR__) {
99
  $this->configTTL = 3600;
100
  $this->siteId = $siteId;
122
  $queryStr = parse_url($url, PHP_URL_QUERY);
123
 
124
  if ($queryStr) {
125
+ $this->nitro_parse_str($queryStr, $queryParams);
126
 
127
  if ($queryParams) {
128
  if ($this->config->IgnoredParams) {
299
  $this->pageCache->useInvalidated(false);
300
  // End of check
301
 
302
+ list($headers, $content) = Filesystem::explodeByHeaders($resp->getBody());
303
+ $this->pageCache->setContent($content, $headers);
304
  return true;
305
  } else {
306
  // The goal is to serve cache at all times even when it is slightly outdated. This approach should be ok because new cache has been requested and it should be ready soon
597
  }
598
 
599
  public function isSecure() {
600
+ $result = (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && in_array("https", array_map("strtolower", array_map("trim", explode(",", $_SERVER['HTTP_X_FORWARDED_PROTO']))))) ||
601
  (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
602
  (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) ||
603
  (!empty($_SERVER['HTTP_SSL_FLAG']) && $_SERVER['HTTP_SSL_FLAG'] == 'SSL');
604
+
605
+ if (!$result && !empty($_SERVER['HTTP_CF_VISITOR'])) {
606
+ $visitor = json_decode($_SERVER['HTTP_CF_VISITOR']);
607
+ $result = $visitor && property_exists($visitor, "scheme") && strtolower($visitor->scheme) == "https";
608
+ }
609
+
610
+ return $result;
611
  }
612
 
613
  public function isAJAXRequest() {
nitropack-sdk/NitroPack/SDK/Pagecache.php CHANGED
@@ -118,12 +118,18 @@ class Pagecache {
118
  $mtime = Filesystem::fileMtime($cachefilePath);
119
  }
120
 
121
- if (time() - $mtime >= $ttl) {
 
 
122
  return true;
123
  } else {
124
  try {
125
  $headers = Filesystem::fileGetHeaders($cachefilePath);
126
- if (!empty($headers["x-nitro-expires"]) && time() > (int)$headers["x-nitro-expires"]) {
 
 
 
 
127
  return true;
128
  }
129
 
@@ -143,9 +149,12 @@ class Pagecache {
143
 
144
  $filePath = $this->getCachefilePath();
145
  if (Filesystem::createDir(dirname($filePath))) {
146
- if (!Filesystem::filePutContents($filePath, $content, $headers)) {
147
  return false;
148
  } else {
 
 
 
149
  return $this->compress($filePath);
150
  }
151
  }
@@ -171,7 +180,14 @@ class Pagecache {
171
  private function compress($filePath) {
172
  $fileInfo = Filesystem::fileGetAll($filePath);
173
  $fileInfo->headers["Content-Encoding"] = "gzip";
174
- return Filesystem::filePutContents($filePath . ".gz", gzencode($fileInfo->content, 4), $this->headersFlatten($fileInfo->headers)); // save compressed version of the cache file
 
 
 
 
 
 
 
175
  }
176
 
177
  public function readfile() {
118
  $mtime = Filesystem::fileMtime($cachefilePath);
119
  }
120
 
121
+ $now = time();
122
+
123
+ if ($now - $mtime >= $ttl) {
124
  return true;
125
  } else {
126
  try {
127
  $headers = Filesystem::fileGetHeaders($cachefilePath);
128
+ if (!empty($headers["x-nitro-expires"]) && $now > (int)$headers["x-nitro-expires"]) {
129
+ return true;
130
+ }
131
+
132
+ if (!empty($headers["x-cache-ctime"]) && $now - (int)$headers["x-cache-ctime"] > $ttl) {
133
  return true;
134
  }
135
 
149
 
150
  $filePath = $this->getCachefilePath();
151
  if (Filesystem::createDir(dirname($filePath))) {
152
+ if (!Filesystem::filePutContents($filePath, $content, $this->headersFlatten($headers))) {
153
  return false;
154
  } else {
155
+ if ($headers && !empty($headers["x-cache-ctime"])) {
156
+ Filesystem::touch($filePath, (int)$headers["x-cache-ctime"]);
157
+ }
158
  return $this->compress($filePath);
159
  }
160
  }
180
  private function compress($filePath) {
181
  $fileInfo = Filesystem::fileGetAll($filePath);
182
  $fileInfo->headers["Content-Encoding"] = "gzip";
183
+ $gzPath = $filePath . ".gz";
184
+ $res = Filesystem::filePutContents($gzPath, gzencode($fileInfo->content, 4), $this->headersFlatten($fileInfo->headers)); // save compressed version of the cache file
185
+
186
+ if ($res && $fileInfo->headers && !empty($fileInfo->headers["x-cache-ctime"])) {
187
+ Filesystem::touch($gzPath, (int)$fileInfo->headers["x-cache-ctime"]);
188
+ }
189
+
190
+ return $res;
191
  }
192
 
193
  public function readfile() {
nitropack-sdk/NitroPack/SDK/StorageDriver/Disk.php CHANGED
@@ -83,8 +83,12 @@ class Disk {
83
  return @filemtime($filePath);
84
  }
85
 
86
- public function touch($filePath) {
87
- return @touch($filePath);
 
 
 
 
88
  }
89
 
90
  public function exists($filePath) {
83
  return @filemtime($filePath);
84
  }
85
 
86
+ public function touch($filePath, $time = NULL) {
87
+ if ($time && is_numeric($time)) {
88
+ return @touch($filePath, (int)$time);
89
+ } else {
90
+ return @touch($filePath);
91
+ }
92
  }
93
 
94
  public function exists($filePath) {
nitropack-sdk/NitroPack/SDK/StorageDriver/Redis.php CHANGED
@@ -31,12 +31,13 @@ class Redis {
31
  return implode(DIRECTORY_SEPARATOR, $parts);
32
  }
33
 
34
- public function touch($path) {
 
35
  $path = $this->preparePathInput($path);
36
  $parent = dirname($path);
37
  $key = basename($path);
38
  if ($this->isDir($parent)) {
39
- $this->redis->hSet($parent, "::mtime::" . $key, time());
40
  $this->redis->hSetNx($parent, "::content::" . $key, "");
41
  return true;
42
  } else {
31
  return implode(DIRECTORY_SEPARATOR, $parts);
32
  }
33
 
34
+ public function touch($path, $time = NULL) {
35
+ if ($time === NULL || !is_numeric($time)) $time = time();
36
  $path = $this->preparePathInput($path);
37
  $parent = dirname($path);
38
  $key = basename($path);
39
  if ($this->isDir($parent)) {
40
+ $this->redis->hSet($parent, "::mtime::" . $key, (int)$time);
41
  $this->redis->hSetNx($parent, "::content::" . $key, "");
42
  return true;
43
  } else {
nitropack-sdk/nitro.start.php CHANGED
@@ -1,4 +1,12 @@
1
  <?php
 
 
 
 
 
 
 
 
2
  // Load NitroPack libraries
3
  require_once('autoload.php');
4
 
1
  <?php
2
+ /**
3
+ ********************************
4
+ * !!! IMPORTANT !!! *
5
+ *DO NOT USE ON NEW INTEGRATIONS*
6
+ * THIS FILE IS DEPRECATED *
7
+ * BACKWARDS COMPATIBILITY ONLY *
8
+ ********************************
9
+ */
10
  // Load NitroPack libraries
11
  require_once('autoload.php');
12
 
nitropack-sdk/vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit3dcb0cd3b9802939155e959c3c6cfd5d::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit8fcbb1a5ffa2542d92b974779798cb81::getLoader();
nitropack-sdk/vendor/composer/ClassLoader.php CHANGED
@@ -37,8 +37,8 @@ namespace Composer\Autoload;
37
  *
38
  * @author Fabien Potencier <fabien@symfony.com>
39
  * @author Jordi Boggiano <j.boggiano@seld.be>
40
- * @see https://www.php-fig.org/psr/psr-0/
41
- * @see https://www.php-fig.org/psr/psr-4/
42
  */
43
  class ClassLoader
44
  {
@@ -60,7 +60,7 @@ class ClassLoader
60
  public function getPrefixes()
61
  {
62
  if (!empty($this->prefixesPsr0)) {
63
- return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
64
  }
65
 
66
  return array();
37
  *
38
  * @author Fabien Potencier <fabien@symfony.com>
39
  * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
  */
43
  class ClassLoader
44
  {
60
  public function getPrefixes()
61
  {
62
  if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
  }
65
 
66
  return array();
nitropack-sdk/vendor/composer/autoload_classmap.php CHANGED
@@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
- 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  );
nitropack-sdk/vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit3dcb0cd3b9802939155e959c3c6cfd5d
6
  {
7
  private static $loader;
8
 
@@ -22,15 +22,15 @@ class ComposerAutoloaderInit3dcb0cd3b9802939155e959c3c6cfd5d
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInit3dcb0cd3b9802939155e959c3c6cfd5d', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInit3dcb0cd3b9802939155e959c3c6cfd5d', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
- require __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInit3dcb0cd3b9802939155e959c3c6cfd5d::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit8fcbb1a5ffa2542d92b974779798cb81
6
  {
7
  private static $loader;
8
 
22
  return self::$loader;
23
  }
24
 
25
+ spl_autoload_register(array('ComposerAutoloaderInit8fcbb1a5ffa2542d92b974779798cb81', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit8fcbb1a5ffa2542d92b974779798cb81', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
+ require_once __DIR__ . '/autoload_static.php';
32
 
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit8fcbb1a5ffa2542d92b974779798cb81::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
nitropack-sdk/vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit3dcb0cd3b9802939155e959c3c6cfd5d
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'N' =>
@@ -26,16 +26,11 @@ class ComposerStaticInit3dcb0cd3b9802939155e959c3c6cfd5d
26
  ),
27
  );
28
 
29
- public static $classMap = array (
30
- 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
31
- );
32
-
33
  public static function getInitializer(ClassLoader $loader)
34
  {
35
  return \Closure::bind(function () use ($loader) {
36
- $loader->prefixLengthsPsr4 = ComposerStaticInit3dcb0cd3b9802939155e959c3c6cfd5d::$prefixLengthsPsr4;
37
- $loader->prefixDirsPsr4 = ComposerStaticInit3dcb0cd3b9802939155e959c3c6cfd5d::$prefixDirsPsr4;
38
- $loader->classMap = ComposerStaticInit3dcb0cd3b9802939155e959c3c6cfd5d::$classMap;
39
 
40
  }, null, ClassLoader::class);
41
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit8fcbb1a5ffa2542d92b974779798cb81
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'N' =>
26
  ),
27
  );
28
 
 
 
 
 
29
  public static function getInitializer(ClassLoader $loader)
30
  {
31
  return \Closure::bind(function () use ($loader) {
32
+ $loader->prefixLengthsPsr4 = ComposerStaticInit8fcbb1a5ffa2542d92b974779798cb81::$prefixLengthsPsr4;
33
+ $loader->prefixDirsPsr4 = ComposerStaticInit8fcbb1a5ffa2542d92b974779798cb81::$prefixDirsPsr4;
 
34
 
35
  }, null, ClassLoader::class);
36
  }
nitropack-sdk/vendor/composer/installed.json CHANGED
@@ -1,73 +1,65 @@
1
- {
2
- "packages": [
3
- {
4
- "name": "nitropack/httpclient",
5
- "version": "dev-master",
6
- "version_normalized": "dev-master",
7
- "source": {
8
- "type": "git",
9
- "url": "git@bitbucket.org:nitropack/httpclient.git",
10
- "reference": "2322728997a9a3e7f4adbb41229b347cce2ebab0"
11
- },
12
- "require": {
13
- "nitropack/url": "dev-master"
14
- },
15
- "time": "2020-12-30T16:50:03+00:00",
16
- "default-branch": true,
17
- "type": "library",
18
- "installation-source": "source",
19
- "autoload": {
20
- "psr-4": {
21
- "NitroPack\\": "src/"
22
- }
23
- },
24
- "authors": [
25
- {
26
- "name": "Ivailo Hristov"
27
- }
28
- ],
29
- "description": "HttpClient library written in PHP, without relying on cURL nor url_fopen",
30
- "keywords": [
31
- "client",
32
- "http",
33
- "library",
34
- "php"
35
- ],
36
- "install-path": "../nitropack/httpclient"
37
  },
38
- {
39
- "name": "nitropack/url",
40
- "version": "dev-master",
41
- "version_normalized": "dev-master",
42
- "source": {
43
- "type": "git",
44
- "url": "git@bitbucket.org:nitropack/url.git",
45
- "reference": "d10e616a333f5a5107137f88313c7ceba638c8a0"
46
- },
47
- "time": "2020-11-04T10:08:34+00:00",
48
- "default-branch": true,
49
- "type": "library",
50
- "installation-source": "source",
51
- "autoload": {
52
- "psr-4": {
53
- "NitroPack\\": "src/"
54
- }
55
- },
56
- "authors": [
57
- {
58
- "name": "Ivailo Hristov"
59
- }
60
- ],
61
- "description": "URL manipulation library",
62
- "keywords": [
63
- "library",
64
- "manipulation",
65
- "php",
66
- "url"
67
- ],
68
- "install-path": "../nitropack/url"
69
- }
70
- ],
71
- "dev": true,
72
- "dev-package-names": []
73
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "nitropack/httpclient",
4
+ "version": "dev-master",
5
+ "version_normalized": "9999999-dev",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "git@bitbucket.org:nitropack/httpclient.git",
9
+ "reference": "b1e792a4e99279d5c5b12cb0a35921d90f0043c2"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  },
11
+ "require": {
12
+ "nitropack/url": "dev-master"
13
+ },
14
+ "time": "2020-11-04T09:25:18+00:00",
15
+ "type": "library",
16
+ "installation-source": "source",
17
+ "autoload": {
18
+ "psr-4": {
19
+ "NitroPack\\": "src/"
20
+ }
21
+ },
22
+ "authors": [
23
+ {
24
+ "name": "Ivailo Hristov"
25
+ }
26
+ ],
27
+ "description": "HttpClient library written in PHP, without relying on cURL nor url_fopen",
28
+ "keywords": [
29
+ "client",
30
+ "http",
31
+ "library",
32
+ "php"
33
+ ]
34
+ },
35
+ {
36
+ "name": "nitropack/url",
37
+ "version": "dev-master",
38
+ "version_normalized": "9999999-dev",
39
+ "source": {
40
+ "type": "git",
41
+ "url": "git@bitbucket.org:nitropack/url.git",
42
+ "reference": "d10e616a333f5a5107137f88313c7ceba638c8a0"
43
+ },
44
+ "time": "2020-11-04T10:08:34+00:00",
45
+ "type": "library",
46
+ "installation-source": "source",
47
+ "autoload": {
48
+ "psr-4": {
49
+ "NitroPack\\": "src/"
50
+ }
51
+ },
52
+ "authors": [
53
+ {
54
+ "name": "Ivailo Hristov"
55
+ }
56
+ ],
57
+ "description": "URL manipulation library",
58
+ "keywords": [
59
+ "library",
60
+ "manipulation",
61
+ "php",
62
+ "url"
63
+ ]
64
+ }
65
+ ]
nitropack-sdk/vendor/nitropack/httpclient/src/HttpClient.php CHANGED
@@ -40,25 +40,6 @@ class HttpClient {
40
  }
41
  }
42
 
43
- public static function drainConnections() {
44
- $connectionsCount = 0;
45
- $connectionsRemovedCount = 0;
46
- foreach (self::$connections as $key => &$connections) {
47
- $connectionsCount += count($connections);
48
- foreach ($connections as $index => $con) {
49
- if (self::_isConnectionValid($con, true)) {
50
- $connectionsRemovedCount++;
51
- self::_disconnect($con);
52
- }
53
- array_splice($connections, $index, 1);
54
- }
55
-
56
- if (empty($connections)) {
57
- unset(self::$connections[$key]);
58
- }
59
- }
60
- }
61
-
62
  public static function _isConnectionValid($sock, $readRemainder = false) {
63
  $isValidStream = is_resource($sock) && get_resource_type($sock) != "Unknown";
64
  if ($isValidStream && $readRemainder) {
@@ -271,13 +252,6 @@ class HttpClient {
271
  self::_disconnect($this->sock);
272
  }
273
 
274
- public function abort() {
275
- $this->disconnect();
276
- if (!empty($this->asyncQueue)) {
277
- $this->asyncQueue = [];
278
- }
279
- }
280
-
281
  public function setURL($URL, $resetRedirects = true) {
282
  if ($resetRedirects) {
283
  $this->redirects_count = 0;
@@ -1335,8 +1309,6 @@ class HttpClient {
1335
  private function error_sink($errno, $errstr) {}
1336
  }
1337
 
1338
- register_shutdown_function(array("\NitroPack\HttpClient", "drainConnections"));
1339
-
1340
  class URLException extends Exception {}
1341
  class URLEmptyException extends Exception {}
1342
  class URLInvalidException extends Exception {}
40
  }
41
  }
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  public static function _isConnectionValid($sock, $readRemainder = false) {
44
  $isValidStream = is_resource($sock) && get_resource_type($sock) != "Unknown";
45
  if ($isValidStream && $readRemainder) {
252
  self::_disconnect($this->sock);
253
  }
254
 
 
 
 
 
 
 
 
255
  public function setURL($URL, $resetRedirects = true) {
256
  if ($resetRedirects) {
257
  $this->redirects_count = 0;
1309
  private function error_sink($errno, $errstr) {}
1310
  }
1311
 
 
 
1312
  class URLException extends Exception {}
1313
  class URLEmptyException extends Exception {}
1314
  class URLInvalidException extends Exception {}
nitropack-sdk/vendor/nitropack/httpclient/src/HttpClientMulti.php CHANGED
@@ -8,7 +8,6 @@ class HttpClientMulti {
8
  private $errorCallback;
9
  private $returnClients;
10
  private $intervals;
11
- private $clientRegistrationTimes;
12
 
13
  public function __construct() {
14
  $this->clients = array();
@@ -16,7 +15,6 @@ class HttpClientMulti {
16
  $this->successCallback = NULL;
17
  $this->errorCallback = NULL;
18
  $this->returnClients = true;
19
- $this->clientRegistrationTimes = new \SplObjectStorage();
20
  }
21
 
22
  public function returnClients($status) {
@@ -25,7 +23,6 @@ class HttpClientMulti {
25
 
26
  public function push($client) {
27
  $this->clients[] = $client;
28
- $this->clientRegistrationTimes->attach($client, time());
29
  }
30
 
31
  public function getClients() {
@@ -174,35 +171,8 @@ class HttpClientMulti {
174
  return [$succeededClients, $failedClients];
175
  }
176
 
177
- public function evictStuckClients($timeout = 300) {
178
- $evictedClients = [];
179
- $now = time();
180
- foreach ($this->clients as $client) {
181
- try {
182
- $clientRegistrationTime = $this->clientRegistrationTimes->offsetGet($client);
183
- } catch (\UnexpectedValueException $e) {
184
- $clientRegistrationTime = 0;
185
- // Weird client - remove it
186
- }
187
-
188
- if ($now - $clientRegistrationTime >= $timeout) {
189
- $evictedClients[] = $client;
190
- $client->abort();
191
- $this->removeClient($client);
192
- }
193
- }
194
-
195
- return $evictedClients;
196
- }
197
-
198
  private function removeClient($client) {
199
  $index = array_search($client, $this->clients, true);
200
- if ($index !== false) { // Index can be false if the client has been evicted earlier
201
- array_splice($this->clients, $index, 1);
202
- }
203
-
204
- if ($this->clientRegistrationTimes->offsetExists($client)) { // Offset may not exist if the client has been evicted earlier
205
- $this->clientRegistrationTimes->detach($client);
206
- }
207
  }
208
  }
8
  private $errorCallback;
9
  private $returnClients;
10
  private $intervals;
 
11
 
12
  public function __construct() {
13
  $this->clients = array();
15
  $this->successCallback = NULL;
16
  $this->errorCallback = NULL;
17
  $this->returnClients = true;
 
18
  }
19
 
20
  public function returnClients($status) {
23
 
24
  public function push($client) {
25
  $this->clients[] = $client;
 
26
  }
27
 
28
  public function getClients() {
171
  return [$succeededClients, $failedClients];
172
  }
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  private function removeClient($client) {
175
  $index = array_search($client, $this->clients, true);
176
+ array_splice($this->clients, $index, 1);
 
 
 
 
 
 
177
  }
178
  }
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: nitropack
3
  Tags: cache,perfomance,optimize,pagespeed,lazy load,cdn,critical css,compression,defer css javascript,minify css,minify,webp
4
  Requires at least: 4.7
5
- Tested up to: 5.7
6
  Requires PHP: 5.3
7
- Stable tag: 1.5.3
8
  License: GNU General Public License, version 2
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -169,6 +169,30 @@ No. We’ve designed NitroPack to be a very lightweight solution that adds no CP
169
 
170
  == Changelog ==
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  = 1.5.4 =
173
  * Change: Bump up the tested-up-to version for WP 5.7
174
  * Bug fix: Resolve a constant already defined error
2
  Contributors: nitropack
3
  Tags: cache,perfomance,optimize,pagespeed,lazy load,cdn,critical css,compression,defer css javascript,minify css,minify,webp
4
  Requires at least: 4.7
5
+ Tested up to: 5.8
6
  Requires PHP: 5.3
7
+ Stable tag: 1.5.5
8
  License: GNU General Public License, version 2
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
169
 
170
  == Changelog ==
171
 
172
+ = 1.5.5 =
173
+ * New Feature: Compatibility with Fastly
174
+ * New Feature: Compatibility with Closte
175
+ * New Feature: Compatibility with Beaver Builder's cache purge
176
+ * New Feature: Compatibility with the Cookie Notice plugin
177
+ * New Feature: Add generic compatibility with LiteSpeed servers
178
+ * Improvement: Better efficiency in the API calls leading to less overhead in admin operations
179
+ * Improvement: Vastly better support for popular cache proxies, making a much better use of existing infrastructure
180
+ * Improvement: Better compatibility with WP Engine
181
+ * Improvement: Better compatibility with Kinsta
182
+ * Improvement: Better compatibility with SiteGround
183
+ * Improvement: Better compatibility with Pagely
184
+ * Improvement: Better compatibility with Cloudways
185
+ * Improvement: Better compatibility with Flywheel
186
+ * Improvement: Clear existing proxy cache when NitroPack is activated or deactivated
187
+ * Improvement: Show more helper messages to guide the administrator in resolving detected issues
188
+ * Improvement: Prevent duplicate connections which were previously causing the cache to get out of sync
189
+ * Improvement: More granular and accurate detection of inventory updates in WooCommerce
190
+ * Improvement: The safe mode prompt is now on the deactivate step
191
+ * Improvement: Handle a specific case of Cloudflare's Flexible SSL coupled with a redirect
192
+ * Bug fix: Resolve an issue with the WooCommerce PayPal Checkout Payment Gateway plugin
193
+ * Bug fix: Various form submission issues have been resolved
194
+ * Many bug fixes and stability improvements
195
+
196
  = 1.5.4 =
197
  * Change: Bump up the tested-up-to version for WP 5.7
198
  * Bug fix: Resolve a constant already defined error
uninstall.php CHANGED
@@ -3,7 +3,7 @@ if (!defined('WP_UNINSTALL_PLUGIN')) {
3
  die;
4
  }
5
 
6
- $nitropackOptions = array('nitropack-siteId', 'nitropack-siteSecret', 'nitropack-enableCompression', 'nitropack-webhookToken', 'nitropack-checkedCompression', 'nitropack-cacheablePostTypes');
7
  if (defined('MULTISITE') && MULTISITE) {
8
  $blogs = array_map(function($blog) { return $blog->blog_id; }, get_sites());
9
 
3
  die;
4
  }
5
 
6
+ $nitropackOptions = array('nitropack-siteId', 'nitropack-siteSecret', 'nitropack-enableCompression', 'nitropack-webhookToken', 'nitropack-checkedCompression', 'nitropack-cacheablePostTypes', 'nitropack-wcNotice', 'nitropack-safeModeStatus', 'nitropack-bbCacheSyncPurge');
7
  if (defined('MULTISITE') && MULTISITE) {
8
  $blogs = array_map(function($blog) { return $blog->blog_id; }, get_sites());
9
 
view/admin.php CHANGED
@@ -14,13 +14,13 @@
14
  </ul>
15
  <div class="tab-content" style="display:block">
16
  <div id="dashboard" class="tab-pane hidden">
17
- <?php require_once "dashboard.php"; ?>
18
  </div>
19
  <div id="help" class="tab-pane hidden">
20
- <?php require_once "help.php"; ?>
21
  </div>
22
  <div id="diag" class="tab-pane hidden">
23
- <?php require_once "diag.php"; ?>
24
  </div>
25
  </div>
26
  </form>
@@ -72,14 +72,33 @@
72
  action: "nitropack_" + clearCacheAction + "_cache"
73
  },
74
  dataType: 'json',
75
- beforeSend: function() {
76
  Notification.info("Loading. Please wait...");
 
 
77
  },
78
  success: function(data) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  Notification[data.type](data.message);
80
-
81
- cacheEvent = new Event("cache." + clearCacheAction + ".success");
82
  window.dispatchEvent(cacheEvent);
 
 
 
83
  }
84
  });
85
  };
14
  </ul>
15
  <div class="tab-content" style="display:block">
16
  <div id="dashboard" class="tab-pane hidden">
17
+ <?php require_once NITROPACK_PLUGIN_DIR . "view/dashboard.php"; ?>
18
  </div>
19
  <div id="help" class="tab-pane hidden">
20
+ <?php require_once NITROPACK_PLUGIN_DIR . "view/help.php"; ?>
21
  </div>
22
  <div id="diag" class="tab-pane hidden">
23
+ <?php require_once NITROPACK_PLUGIN_DIR . "view/diag.php"; ?>
24
  </div>
25
  </div>
26
  </form>
72
  action: "nitropack_" + clearCacheAction + "_cache"
73
  },
74
  dataType: 'json',
75
+ beforeSend: function() {
76
  Notification.info("Loading. Please wait...");
77
+ $('#optimizations-purge-cache').hide();
78
+ $('#np-purge-cache-loading').show();
79
  },
80
  success: function(data) {
81
+ $('#np-purge-cache-loading').hide();
82
+ if (data.type === 'success') {
83
+ $('#np-purge-cache-success').show();
84
+ Notification[data.type](data.message);
85
+ cacheEvent = new Event("cache." + clearCacheAction + ".success");
86
+ } else {
87
+ $('#np-purge-cache-error').show();
88
+ Notification[data.type](data.message);
89
+ cacheEvent = new Event("cache." + clearCacheAction + ".error");
90
+ }
91
+ window.dispatchEvent(cacheEvent);
92
+ },
93
+ error: function(data) {
94
+ $('#np-purge-cache-loading').hide();
95
+ $('#np-purge-cache-error').show();
96
  Notification[data.type](data.message);
97
+ cacheEvent = new Event("cache." + clearCacheAction + ".error");
 
98
  window.dispatchEvent(cacheEvent);
99
+ },
100
+ complete: function() {
101
+ setTimeout(function(){$('#np-purge-cache-success').hide();$('#np-purge-cache-error').hide();$('#optimizations-purge-cache').show();}, 3000);
102
  }
103
  });
104
  };
view/dashboard.php CHANGED
@@ -21,6 +21,9 @@
21
  <div class="optimizations-subcount"><span data-optimized-pages-desktop>0</span> desktop pages</div>
22
  </div>
23
  <div class="row mt-5 justify-content-center">
 
 
 
24
  <button id="optimizations-purge-cache" class="btn btn-light btn-outline-secondary btn-widget-optimizations">Purge Cache</button>
25
  </div>
26
  </div>
@@ -159,6 +162,19 @@
159
  </label>
160
  </span>
161
  </li>
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  <li class="list-group-item px-0 d-flex justify-content-between align-items-center">
163
  <span>Select what post/page types get optimized</span>
164
  <span id="cacheable-post-types-btn">
@@ -221,6 +237,7 @@
221
  <script>
222
  ($ => {
223
  var getOptimizationsTimeout = null;
 
224
 
225
  $(window).on("load",function() {
226
  $("#optimizations-widget").cardOverlay("loading", {message: "Loading optimizations data"});
@@ -254,11 +271,41 @@
254
  $(document).on('click', '#optimizations-purge-cache', function(e) {
255
  e.preventDefault();
256
  //Overlay.loading("Purging cache...");
257
-
258
  purgeEvent = new Event("cache.purge.request");
259
  window.dispatchEvent(purgeEvent);
260
  });
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  $("#btn-run-warmup").on("click", function(e) {
263
  runWarmup();
264
  })
@@ -488,7 +535,11 @@
488
  }
489
 
490
  window.addEventListener("cache.invalidate.success", getOptimizations);
491
- window.addEventListener("cache.purge.success", getOptimizations);
 
 
 
 
492
 
493
 
494
  var autoDetectCompression = function() {
@@ -533,6 +584,15 @@
533
  });
534
  });
535
 
 
 
 
 
 
 
 
 
 
536
  $("#save-cacheable-post-types").on("click", function(e) {
537
  $(this).find("i").removeClass("d-none");
538
  $.ajax({
@@ -579,16 +639,11 @@
579
  $("#settings-widget").cardOverlay("clear");
580
  }
581
 
582
- window.safemodeOnDisconnect = function() {
583
- enableSafemode();
584
- $("#settings-widget").cardOverlay("clear");
585
- }
586
-
587
  $(document).on('click', "#disconnect-btn", e => {
588
  e.preventDefault();
589
 
590
- var confirmHtml = '<p>Did you know that NitroPack offers a safe mode? We recommend using it instead of disconnecting. Are you sure that you wish to disconnect?</p>';
591
- confirmHtml += '<p id="disconnectConfirmBtns"><a href="javascript:void(0);" onclick="rejectDisconnect()" class="btn btn-default btn-sm">No</a>&nbsp;&nbsp;<a href="javascript:void(0);" onclick="safemodeOnDisconnect()" class="btn btn-primary btn-sm">Enable Safe Mode</a>&nbsp;&nbsp;<a href="javascript:void(0);" onclick="confirmDisconnect()" class="btn btn-info btn-sm">Disconnect</a></p>';
592
  $("#settings-widget").cardOverlay("notify", {message: confirmHtml});
593
  });
594
 
21
  <div class="optimizations-subcount"><span data-optimized-pages-desktop>0</span> desktop pages</div>
22
  </div>
23
  <div class="row mt-5 justify-content-center">
24
+ <i id="np-purge-cache-loading"class="fa fa-refresh fa-spin" style="margin:5px;font-size:48px;display:none;"></i>
25
+ <i id="np-purge-cache-success" class="fa fa-check-circle" style="margin:5px;font-size:48px;display:none;"></i>
26
+ <i id="np-purge-cache-error" class="fa fa-times-circle" style="margin:5px;font-size:48px;display:none;"></i>
27
  <button id="optimizations-purge-cache" class="btn btn-light btn-outline-secondary btn-widget-optimizations">Purge Cache</button>
28
  </div>
29
  </div>
162
  </label>
163
  </span>
164
  </li>
165
+ <?php if (\NitroPack\Integration\Plugin\BeaverBuilder::isActive()) { ?>
166
+ <li class="list-group-item px-0 d-flex justify-content-between align-items-center">
167
+ <span>Purge NitroPack cache when Beaver Builder cache is purged<br/>
168
+ <small>Warning: This will perform a full NitroPack cache purge</small>
169
+ </span>
170
+ <span id="bb-purge-toggle">
171
+ <label id="bb-purge-status-slider" class="switch">
172
+ <input type="checkbox" id="bb-purge-status" <?php if ($bbCacheSyncPurge) echo "checked"; ?>>
173
+ <span class="slider"></span>
174
+ </label>
175
+ </span>
176
+ </li>
177
+ <?php } ?>
178
  <li class="list-group-item px-0 d-flex justify-content-between align-items-center">
179
  <span>Select what post/page types get optimized</span>
180
  <span id="cacheable-post-types-btn">
237
  <script>
238
  ($ => {
239
  var getOptimizationsTimeout = null;
240
+ let isClearing = false;
241
 
242
  $(window).on("load",function() {
243
  $("#optimizations-widget").cardOverlay("loading", {message: "Loading optimizations data"});
271
  $(document).on('click', '#optimizations-purge-cache', function(e) {
272
  e.preventDefault();
273
  //Overlay.loading("Purging cache...");
 
274
  purgeEvent = new Event("cache.purge.request");
275
  window.dispatchEvent(purgeEvent);
276
  });
277
 
278
+ $(document).on('click', '[nitropack-rc-data]', function(e) {
279
+ e.preventDefault();
280
+ if (isClearing) return;
281
+ let currentButton = $(this);
282
+ $.ajax({
283
+ url: ajaxurl,
284
+ type: "POST",
285
+ dataType: "text",
286
+ data: {
287
+ action: 'nitropack_clear_residual_cache',
288
+ gde: currentButton.attr('nitropack-rc-data')
289
+ },
290
+ beforeSend: function () {
291
+ currentButton.parent(".alert-warning").hide();
292
+ isClearing = true;
293
+ },
294
+ success: function(resp) {
295
+ result = JSON.parse(resp);
296
+ Notification[result.type](result.message);
297
+ },
298
+ error: function(resp) {
299
+ result = JSON.parse(resp);
300
+ Notification[result.type](result.message);
301
+ },
302
+ complete: function() {
303
+ isClearing = false;
304
+ setTimeout(function(){location.reload();}, 3000);
305
+ }
306
+ });
307
+ });
308
+
309
  $("#btn-run-warmup").on("click", function(e) {
310
  runWarmup();
311
  })
535
  }
536
 
537
  window.addEventListener("cache.invalidate.success", getOptimizations);
538
+ if ($('#np-onstate-cache-purge').length) {
539
+ window.addEventListener("cache.purge.success", function(){setTimeout(function(){document.cookie = "nitropack_apwarning=1; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=<?php echo nitropack_cookiepath(); ?>"; window.location.reload()}, 1500)});
540
+ } else {
541
+ window.addEventListener("cache.purge.success", getOptimizations);
542
+ }
543
 
544
 
545
  var autoDetectCompression = function() {
584
  });
585
  });
586
 
587
+ $("#bb-purge-status").on("click", function(e) {
588
+ $.post(ajaxurl, {
589
+ action: 'nitropack_set_bb_cache_purge_sync_ajax',
590
+ bbCachePurgeSyncStatus: $(this).is(":checked") ? 1 : 0
591
+ }, function(response) {
592
+ Notification.success('Beaver Builder cache purge sync settings are saved.');
593
+ });
594
+ });
595
+
596
  $("#save-cacheable-post-types").on("click", function(e) {
597
  $(this).find("i").removeClass("d-none");
598
  $.ajax({
639
  $("#settings-widget").cardOverlay("clear");
640
  }
641
 
 
 
 
 
 
642
  $(document).on('click', "#disconnect-btn", e => {
643
  e.preventDefault();
644
 
645
+ var confirmHtml = '<p>Are you sure that you wish to disconnect?</p>';
646
+ confirmHtml += '<p id="disconnectConfirmBtns"><a href="javascript:void(0);" onclick="rejectDisconnect()" class="btn btn-default btn-sm">No</a>&nbsp;&nbsp;<a href="javascript:void(0);" onclick="confirmDisconnect()" class="btn btn-info btn-sm">Disconnect</a></p>';
647
  $("#settings-widget").cardOverlay("notify", {message: confirmHtml});
648
  });
649
 
view/diag.php CHANGED
@@ -52,7 +52,7 @@
52
  </li>
53
  <li class="list-group-item px-0 d-flex justify-content-between align-items-center">
54
  <span id="loading-dir-info">
55
- Include directory info(structure,permisions)
56
  </span>
57
  <span id="dir-info-toggle">
58
  <label id="dir-info-slider" class="switch">
@@ -75,15 +75,7 @@
75
  </div>
76
  </div>
77
  <script>
78
- /*
79
- var toggled01 = {"general-info-status":document.getElementById("general-info-status").checked ,
80
- "active-plugins-status":document.getElementById("active-plugins-status").checked ,
81
- "user-config-status":document.getElementById("user-config-status").checked ,
82
- "dir-info-status":document.getElementById("dir-info-status").checked
83
- };function() {
84
- Notification.success('Report generated');
85
- }
86
- */
87
  ($ => {
88
  let isReportGenerating = false;
89
 
52
  </li>
53
  <li class="list-group-item px-0 d-flex justify-content-between align-items-center">
54
  <span id="loading-dir-info">
55
+ Include directory info(structure,permissions)
56
  </span>
57
  <span id="dir-info-toggle">
58
  <label id="dir-info-slider" class="switch">
75
  </div>
76
  </div>
77
  <script>
78
+
 
 
 
 
 
 
 
 
79
  ($ => {
80
  let isReportGenerating = false;
81
 
view/javascript/np_safemode.js ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ($) {
2
+ $(window).on("load", function () {
3
+ let deactivateLink = 'tr[data-slug="nitropack"] #deactivate-nitropack';
4
+ let deactivateLinkUrl = $(deactivateLink).attr('href');
5
+
6
+ $(deactivateLink).parent().append($('#nitropack-safemode-popup'));
7
+
8
+
9
+ $(deactivateLink).on('click', function (e) {
10
+ e.preventDefault();
11
+ $('#nitropack-safemode-veil').show();
12
+ $('#nitropack-safemode-popup').show();
13
+ let ref1 = $(window).scrollTop()+$(window).height();
14
+ let ref2 = $('#nitropack-safemode-popup').offset().top + $('#nitropack-safemode-popup').outerHeight(true);
15
+ if (ref2 > ref1) {
16
+ $('html,body').animate({scrollTop: $('#nitropack-safemode-popup').offset().top - ($(window).height() - $('#nitropack-safemode-popup').outerHeight(true) - 10)}, 200);
17
+ }
18
+
19
+ $('#nitropack-safemode-veil').on('click', function () {
20
+ $('#nitropack-safemode-popup').hide();
21
+ $('#nitropack-safemode-veil').hide();
22
+ });
23
+ });
24
+
25
+ $('#np-safemode-nogo').on('click', function (e) {
26
+ e.preventDefault();
27
+ e.stopPropagation();
28
+ $(deactivateLink).unbind('click');
29
+ $('#nitropack-safemode-popup').hide();
30
+ $('#nitropack-safemode-popup').remove();
31
+ if (deactivateLinkUrl !== '') {location.href = deactivateLinkUrl;}
32
+ });
33
+
34
+ $('#np-safemode-go').on('click', function (e) {
35
+ e.preventDefault();
36
+ e.stopPropagation();
37
+ $(deactivateLink).unbind('click');
38
+
39
+ $.ajax({
40
+ url: ajaxurl,
41
+ type: 'POST',
42
+ data: {action: 'nitropack_enable_safemode'},
43
+ beforeSend: function () {
44
+ $('#nitropack-safemode-popup').height($('#np-safemode-content').height());
45
+ $('#np-safemode-content').hide();
46
+ $('#np-safemode-loader-loading').show();
47
+ },
48
+ success: function (response) {
49
+ $('#np-safemode-loader-loading').hide();
50
+ let responseResult = JSON.parse(response);
51
+ if (responseResult.type === 'success') {
52
+ $('#np-safemode-loader-success').show();
53
+ } else {
54
+ $('#np-safemode-loader-error').show();
55
+ }
56
+ },
57
+ error: function () {
58
+ $('#np-safemode-loader-loading').hide();
59
+ $('#np-safemode-loader-error').show();
60
+ },
61
+ complete: function() {
62
+ setTimeout(function(){
63
+ $('#np-safemode-loader-success').hide();
64
+ $('#np-safemode-loader-error').hide();
65
+ $('#nitropack-safemode-popup').remove();
66
+ $('#nitropack-safemode-veil').hide();
67
+ }, 1500);
68
+ }
69
+ });
70
+ });
71
+ });
72
+ })(jQuery);
view/safemode.tpl ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="nitropack-safemode-popup">
2
+ <i id="np-safemode-loader-loading" class="fa fa-refresh fa-spin np-safemode-loader-icon" style="display:none;"></i>
3
+ <i id="np-safemode-loader-success" class="fa fa-check-circle np-safemode-loader-icon" style="display:none;"></i>
4
+ <i id="np-safemode-loader-error" class="fa fa-times-circle np-safemode-loader-icon" style="display:none;"></i>
5
+ <div id="np-safemode-content">
6
+ <div class="np-safemode-title">
7
+ Did you know...
8
+ </div>
9
+ <div class="np-safemode-msg">
10
+ It is not necessary to deactivate NitroPack for troubleshooting.
11
+ You can use our <a href="https://support.nitropack.io/hc/en-us/articles/360060910574-Safe-Mode" target="blank">Safe Mode</a> instead. Do you still want to deactivate?
12
+ </div>
13
+ <div class="np-safemode-controls">
14
+ <a id="np-safemode-nogo" class="btn btn-main" type="submit" name="np-safemode-nogo" >Yes, deactivate</a>&nbsp;
15
+ <a id="np-safemode-go" class="btn btn-sec" type="submit" name="np-safemode-go" >No, enable "Safe Mode"</a>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ <div id="nitropack-safemode-veil"></div>
view/stylesheet/np_safemode.css ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .np-safemode-title {
2
+ position: relative;
3
+ background-color: #674399;
4
+ padding: 15px;
5
+ margin: 0;
6
+ font-size: 17px;
7
+ padding: 15px;
8
+ color: #fff;
9
+ font-weight: 600;
10
+ text-align: center;
11
+ letter-spacing: 0.5px;
12
+ border-top-left-radius: 30px;
13
+ }
14
+
15
+ .np-safemode-msg {
16
+ position: relative;
17
+ background-color: #1b004e;
18
+ padding: 20px;
19
+ font-size: 15px;
20
+ color: #fff;
21
+ font-weight: 400;
22
+ text-align: center;
23
+ letter-spacing: 0.5px;
24
+ }
25
+
26
+ .np-safemode-controls {
27
+ display: flex;
28
+ flex-wrap: wrap;
29
+ width: 100%;
30
+ padding-top: 20px;
31
+ padding-bottom: 10px;
32
+ background-color: #1b004e;
33
+ border-bottom-right-radius: 30px;
34
+ }
35
+
36
+ .btn {
37
+ display: flex;
38
+ margin: auto;
39
+ padding: 0 15px 0 15px;
40
+ font-weight: 400;
41
+ cursor: pointer;
42
+ text-align: center;
43
+ align-items: center;
44
+ user-select: none;
45
+ border: 0px solid transparent;
46
+ height: 40px;
47
+ border-radius: 30px;
48
+ }
49
+
50
+ .btn-sec {
51
+ color: #fff;
52
+ background-color: #4600cc;
53
+ }
54
+
55
+ a.btn-sec:hover{
56
+ color: #fff;
57
+ }
58
+
59
+ .btn-main {
60
+ color: #212529;
61
+ background-color: #0addb5;
62
+ }
63
+
64
+ a.btn-main:hover{
65
+ color: #212529;
66
+ }
67
+
68
+ #nitropack-safemode-popup {
69
+ display: none;
70
+ position: absolute;
71
+ white-space: normal;
72
+ max-width: 400px;
73
+ width: 400px;
74
+ background: #1b004e;
75
+ z-index: 10001;
76
+ border: 0px solid #1b004e;
77
+ border-radius: 30px 0;
78
+ box-shadow: 0 0 20px -5px rgba(0, 0, 0, 0.5);
79
+ left: 0;
80
+ text-align: center;
81
+ }
82
+
83
+ @media (max-width: 768px) {
84
+ #nitropack-safemode-popup {
85
+ position: absolute;
86
+ max-width: 100%;
87
+ left: 0;
88
+ }
89
+ }
90
+
91
+ #nitropack-safemode-veil {
92
+ display: none;
93
+ position: fixed;
94
+ content: "";
95
+ background-color: rgba(0, 0, 0, 0.5);
96
+ top: 0;
97
+ bottom: 0;
98
+ right: 0;
99
+ left: 0;
100
+ z-index: 10000;
101
+ }
102
+
103
+ i.np-safemode-loader-icon {
104
+ font-size: 40px;
105
+ position: relative;
106
+ top:50%;
107
+ }