PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.18.2
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.18.2
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / classes / WordPress / Notifications / Notifications.php
nitropack / classes / WordPress / Notifications Last commit date
AppNotifications.php 1 year ago Notifications.php 11 months ago
Notifications.php
755 lines
1 <?php
2 namespace NitroPack\WordPress\Notifications;
3
4 use NitroPack\WordPress\Settings\TestMode;
5 /*
6 * Class Notifications
7 *
8 * This class handles the notifications for the NitroPack plugin in WordPress.
9 *
10 * @package NitroPack\WordPress\Notifications
11 */
12 class Notifications {
13 private static $instance = NULL;
14 public function __construct() {
15
16 add_action( 'admin_init', [ $this, 'move_existing_notices' ] );
17 add_action( 'admin_notices', [ $this, 'nitropack_admin_notices' ] );
18 /* Using 'init' because it fixes issue when get_home_url() in updateCurrentBlogConfig() is not found in multisites */
19 add_action( 'init', function () {
20 add_action( 'plugins_loaded', [ $this, 'nitropack_plugin_notices' ] );
21 } );
22 //ajax
23 add_action( 'wp_ajax_nitropack_safemode_notification', [ $this, 'nitropack_safemode_notification' ] );
24 add_action( 'wp_ajax_nitropack_dismiss_permanently_notification', [ $this, 'nitropack_dismiss_permanently_notification' ] );
25 add_action( 'wp_ajax_nitropack_dismiss_notification_by_transient', [ $this, 'nitropack_dismiss_notification_by_transient' ] );
26 add_action( 'wp_ajax_nitropack_conflict_plugin_deactivate', [ $this, 'nitropack_conflict_plugin_deactivate' ] );
27
28 }
29 public static function getInstance() {
30 if ( ! self::$instance ) {
31 self::$instance = new Notifications();
32 }
33
34 return self::$instance;
35 }
36
37 /**
38 * Displays general admin notices for the NitroPack plugin in WordPress dashboard.
39 *
40 * @return void
41 */
42 public function nitropack_admin_notices() {
43 $components = new \NitroPack\WordPress\Settings\Components;
44 if ( defined( 'NITROPACK_DATA_DIR_WARNING' ) ) {
45 $components->render_notification( NITROPACK_DATA_DIR_WARNING, 'warning', 'Unable to initialize cache dir' );
46 }
47
48 if ( defined( 'NITROPACK_PLUGIN_DATA_DIR_WARNING' ) ) {
49 $components->render_notification( NITROPACK_PLUGIN_DATA_DIR_WARNING, 'warning', 'Unable to initialize plugin data dir' );
50 }
51
52 if ( ! empty( $_COOKIE["nitropack_after_activate_notice"] ) ) {
53 $components->render_notification( "<script>document.cookie = 'nitropack_after_activate_notice=1; expires=Thu, 01 Jan 1970 00:00:01 GMT;';</script> Go to its' settings to connect it in order to start optimizing your site.",
54 'info',
55 esc_html__( 'NitroPack activated but not connected', 'nitropack' ),
56 '<a href="' . admin_url( 'admin.php?page=nitropack' ) . '">' . esc_html__( 'NitroPack Settings', 'nitropack' ) . '</a>' );
57 }
58
59 $this->render_app_notifications();
60 $this->nitropack_print_hosting_notice();
61 $this->nitropack_print_woocommerce_notice();
62 }
63 /**
64 * Display NitroPack plugin notices in the WordPress admin area.
65 *
66 * This function is responsible for showing various notifications related to the NitroPack plugin.
67 *
68 * @return null|array
69 */
70 public function nitropack_plugin_notices() {
71 if ( ! $this->pass_notification_capabilities() )
72 return;
73
74 static $npPluginNotices = NULL;
75
76 if ( $npPluginNotices !== NULL ) {
77 return $npPluginNotices;
78 }
79
80 $errors = [];
81 $warnings = [];
82 $infos = [];
83
84 /* Sets a warning if there are any conflicting plugins - mostly caching plugins. */
85 $conflictingPlugins = \NitroPack\WordPress\ConflictingPlugins::getInstance();
86 $conflictingPlugins_list = $conflictingPlugins->nitropack_get_conflicting_plugins();
87
88 if ( $conflictingPlugins_list ) {
89
90 foreach ( $conflictingPlugins_list as $clashingPlugin ) {
91 $warnings[] = array(
92 'title' => sprintf( "%s is active and may conflict with NitroPack", $clashingPlugin['name'] ),
93 'msg' => esc_html__( "Some of its features overlap with NitroPack's optimizations which could lead to issues. We recommend disabling it to avoid potential conflicts.", 'nitropack' ),
94 'actions' => '<a href="#" class="btn btn-secondary" data-modal-target="modal-plugin-deactivate" data-modal-toggle="modal-plugin-deactivate" title="Disable ' . $clashingPlugin['name'] . ' ">' . sprintf( "Deactivate %s", $clashingPlugin['name'] ) . '</a>',
95 'classes' => [ 'conflicting-plugins plugin-' . sanitize_title( $clashingPlugin['name'] ) ],
96 );
97 require_once NITROPACK_PLUGIN_DIR . 'view/modals/modal-plugin-deactivate.php';
98 }
99
100 }
101 /* Add residual cache notices if found */
102 $residualCachePlugins = \NitroPack\Integration\Plugin\RC::detectThirdPartyCaches();
103 foreach ( $residualCachePlugins as $rcpName ) {
104 $warnings[] = array(
105 'title' => esc_html__( "Residual cache files", 'nitropack' ),
106 'msg' => sprintf( esc_html__( 'We found residual cache files from %s. These files can interfere with the caching process and must be deleted.', 'nitropack' ), $rcpName, $rcpName ),
107 'actions' => '<a class="btn btn-warning" nitropack-rc-data="' . $rcpName . '">' . esc_html__( 'Delete now', 'nitropack' ) . '</a>',
108 );
109 }
110 /* Sets a warning if there is any activity in the plugins such as new activations, updates, or deletions. */
111 if ( isset( $_COOKIE['nitropack_apwarning'] ) ) {
112 $cookie_path = nitropack_cookiepath();
113 $warnings[] = array(
114 'title' => esc_html__( "Plugins activity", 'nitropack' ),
115 'msg' => esc_html__( 'It seems plugins have been activated, deactivated or updated. It is recommended that you purge the cache to reflect the latest changes.', 'nitropack' ),
116 'actions' => "<a class=\"btn btn-secondary\" href=\"javascript:void(0);\" id=\"np-onstate-cache-purge\" onclick=\"document.cookie = 'nitropack_apwarning=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=$cookie_path';window.location.reload();\">" . esc_html__( 'Dismiss', 'nitropack' ) . "</a>",
117 'classes' => [ 'plugins-state' ],
118 );
119 }
120
121 /* Sets a warning if the Test Mode is enabled. */
122 $smStatus = get_option( 'nitropack-safeModeStatus', "-1" );
123 if ( $smStatus === "-1" ) {
124 $smStatus = TestMode::getInstance()->nitropack_safemode_status( true );
125 }
126 if ( $smStatus ) {
127 $safeModeMessage = __( 'Visitors are accessing your unoptimized pages. Make sure to disable it once you are done testing.', 'nitropack' );
128 if ( get_nitropack()->getDistribution() == "oneclick" ) {
129 $safeModeMessage = apply_filters( "nitropack_oneclick_safemode_message", $safeModeMessage );
130 }
131
132 $warnings[] = array(
133 'title' => esc_html__( "Test Mode Enabled", 'nitropack' ),
134 'msg' => $safeModeMessage,
135 'classes' => [ 'test-mode' ],
136 );
137 }
138
139 $nitropackIsConnected = get_nitropack()->isConnected();
140
141 if ( $nitropackIsConnected ) {
142 if ( nitropack_is_advanced_cache_allowed() ) {
143 $notification_title = esc_html__( "File advanced-cache.php cannot be created", 'nitropack' );
144 $notification_class = [ 'advanced-cache' ];
145
146 if ( ! nitropack_has_advanced_cache() ) {
147
148 $advancedCacheFile = nitropack_trailingslashit( WP_CONTENT_DIR ) . 'advanced-cache.php';
149 if ( ! file_exists( $advancedCacheFile ) || strpos( file_get_contents( $advancedCacheFile ), "NITROPACK_ADVANCED_CACHE" ) === false ) { // For some reason we get the notice right after connecting (even though the advanced-cache file is already in place). This check works around this issue :(
150
151 if ( nitropack_install_advanced_cache() ) {
152 if ( ! \NitroPack\Integration\Hosting\WPEngine::detect() ) { // The advanced-cache.php file in WP Engine is reset fairly often and we don't want to show the notice every time. This is an info we can skip in this case.
153
154 /* Sets an info notifications if the advanced-cache.php file was re-installed. */
155 $infos[] = array(
156 'title' => esc_html__( 'File advanced-cache.php re-installed', 'nitropack' ),
157 'msg' => esc_html__( 'The file /wp-content/advanced-cache.php was either missing or not the one generated by NitroPack. NitroPack re-installed its version of the file, so it can function properly. Possibly, there is another active page caching plugin in your system. For correct operation, please deactivate any other page caching plugins.', 'nitropack' ),
158 'actions' => '<a href="' . admin_url() . 'plugins.php" target="_blank" class="btn btn-secondary">' . esc_html__( 'Plugins page' ) . '</a>',
159 'classes' => $notification_class,
160 );
161 }
162 } else {
163 if ( ! $conflictingPlugins->nitropack_is_conflicting_plugin_active() ) {
164
165 /* Sets an error notifications for not being able to create the advanced-cache.php file due to conflicting caching plugins */
166
167 $errors[] = array(
168 'title' => $notification_title,
169 'msg' => __( 'Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' ),
170 'classes' => $notification_class,
171 );
172 }
173 }
174 }
175 } else {
176 if ( ! defined( "NITROPACK_ADVANCED_CACHE_VERSION" ) || NITROPACK_VERSION != NITROPACK_ADVANCED_CACHE_VERSION ) {
177 if ( ! nitropack_install_advanced_cache() ) {
178 if ( $conflictingPlugins->nitropack_is_conflicting_plugin_active() ) {
179 $errors[] = array(
180 'title' => $notification_title,
181 'msg' => esc_html__( 'The file /wp-content/advanced-cache.php cannot be created because a conflicting plugin is active. Please make sure to disable all conflicting plugins.', 'nitropack' ),
182 'actions' => '<a href="' . admin_url() . 'plugins.php" target="_blank" class="btn btn-primary">Plugins page</a>',
183 'classes' => $notification_class,
184 );
185 } else {
186 $errors[] = array(
187 'title' => $notification_title,
188 'msg' => esc_html__( 'The file /wp-content/advanced-cache.php cannot be created. Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' ),
189 'classes' => $notification_class,
190 );
191 }
192 }
193 }
194 }
195 } else {
196 if ( nitropack_has_advanced_cache() ) {
197 nitropack_uninstall_advanced_cache();
198 }
199 }
200
201 if ( ( ! defined( "WP_CACHE" ) || ! WP_CACHE ) ) {
202 $notification_class = [ 'wp-cache' ];
203 if ( \NitroPack\Integration\Hosting\Flywheel::detect() ) { // Flywheel: This is configured throught the FW control panel
204 $warnings[] = array(
205 'title' => esc_html__( "WP_CACHE not enabled", 'nitropack' ),
206 'msg' => esc_html__( "Please go to your FlyWheel control panel and enable this setting.", 'nitropack' ),
207 'actions' => '<a href="https://getflywheel.com/wordpress-support/how-to-enable-wp_cache/" target="_blank" class="btn btn-primary">View more</a>',
208 'classes' => $notification_class,
209 );
210 } else if ( ! nitropack_set_wp_cache_const( true ) ) {
211 $errors[] = array(
212 'title' => esc_html__( 'Constant WP_CACHE cannot be set', 'nitropack' ),
213 'msg' => esc_html__( 'This can lead to slower cache delivery. Please make sure that the /wp-config.php file is writable and refresh this page.', 'nitropack' ),
214 'classes' => $notification_class,
215 );
216 }
217 }
218
219 if ( apply_filters( 'nitropack_needs_htaccess_changes', false ) ) {
220 if ( ! nitropack_set_htaccess_rules( true ) ) {
221 $warnings[] = array(
222 'title' => esc_html__( "File .htaccess is not writable", 'nitropack' ),
223 'msg' => esc_html__( 'Unable to configure LiteSpeed specific rules for maximum performance. Please make sure your .htaccess file is writable or contact support.', 'nitropack' ),
224 'classes' => [ 'htaccess' ],
225 );
226 }
227 }
228
229 if ( ! get_nitropack()->dataDirExists() && ! get_nitropack()->initDataDir() ) {
230 $errors[] = array(
231 'title' => esc_html__( 'NitroPack data directory cannot be created', 'nitropack' ),
232 'msg' => esc_html__( 'Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' ),
233 'classes' => [ 'np-data-dir' ],
234 );
235 return [
236 'error' => $errors,
237 'warning' => $warnings,
238 'info' => $infos
239 ];
240 }
241
242 if ( ! get_nitropack()->pluginDataDirExists() && ! get_nitropack()->initPluginDataDir() ) {
243 $errors[] = array(
244 'title' => esc_html__( 'NitroPack plugin data directory cannot be created', 'nitropack' ),
245 'msg' => esc_html__( 'Please make sure that the /wp-content/ directory is writable and refresh this page.', 'nitropack' ),
246
247 'classes' => [ 'np-data-dir' ],
248 );
249 return [
250 'error' => $errors,
251 'warning' => $warnings,
252 'info' => $infos
253 ];
254 }
255
256 $siteConfig = nitropack_get_site_config();
257 $siteId = $siteConfig ? $siteConfig["siteId"] : NULL;
258 $siteSecret = $siteConfig ? $siteConfig["siteSecret"] : NULL;
259 $webhookToken = esc_attr( get_option( 'nitropack-webhookToken' ) );
260 $blogId = get_current_blog_id();
261 $isConfigOutdated = ! nitropack_is_config_up_to_date();
262 if ( ! get_nitropack()->Config->exists() && ! get_nitropack()->updateCurrentBlogConfig( $siteId, $siteSecret, $blogId ) ) {
263 $errors[] = array(
264 'title' => esc_html__( "NitroPack static config file cannot be created", 'nitropack' ),
265 'msg' => esc_html__( 'Please make sure that the /wp-content/config-nitropack/ directory is writable and refresh this page.', 'nitropack' ),
266 );
267 } else if ( $isConfigOutdated ) {
268 if ( ! get_nitropack()->updateCurrentBlogConfig( $siteId, $siteSecret, $blogId ) ) {
269 $errors[] = array(
270 'title' => esc_html__( "NitroPack static config file cannot be updated", 'nitropack' ),
271 'msg' => esc_html__( 'Please make sure that the /wp-content/config-nitropack/ directory is writable and refresh this page.', 'nitropack' ),
272 );
273 } else {
274
275 if ( ! $siteConfig ) {
276 nitropack_event( "update" );
277 } else {
278 $prevVersion = ! empty( $siteConfig["pluginVersion"] ) ? $siteConfig["pluginVersion"] : "1.1.4 or older";
279 nitropack_event( "update", null, array( "previous_version" => $prevVersion ) );
280 if ( empty( $siteConfig["pluginVersion"] ) || version_compare( $siteConfig["pluginVersion"], "1.4", "<" ) ) {
281 $nitropack_v1_3_notice_id = 'nitropack_upgrade_to_1_3';
282 }
283 }
284 }
285
286 try {
287 nitropack_setup_webhooks( get_nitropack_sdk(), $webhookToken );
288 } catch (\NitroPack\SDK\WebhookException $e) {
289 $warnings[] = array(
290 'title' => esc_html__( "Unable to configure webhooks", 'nitropack' ),
291 'msg' => esc_html__( 'This can impact the stability of the plugin. Please disconnect and connect again in order to retry configuring the webhooks.', 'nitropack' ),
292 );
293 }
294 } else {
295 $optionsMismatch = false;
296 if ( array_key_exists( 'options_cache', $siteConfig ) ) {
297 foreach ( \NitroPack\WordPress\NitroPack::$optionsToCache as $opt ) {
298 if ( is_array( $opt ) ) {
299 foreach ( $opt as $option => $suboption ) {
300 // Handle both nested and flat structures
301 if ( is_array( $suboption ) ) {
302 // Nested structure
303 if ( ! isset( $siteConfig['options_cache'][ $option ] ) || ! is_array( $siteConfig['options_cache'][ $option ] ) ) {
304 $optionsMismatch = true;
305 break 2;
306 }
307 foreach ( $suboption as $subkey => $subvalue ) {
308 if (
309 ! isset( $siteConfig['options_cache'][ $option ][ $subkey ] ) ||
310 $siteConfig['options_cache'][ $option ][ $subkey ] !== get_option( $option )[ $subkey ]
311 ) {
312 $optionsMismatch = true;
313 break 3;
314 }
315 }
316 } else {
317 // Flat structure within the nested loop
318 if (
319 ! isset( $siteConfig['options_cache'][ $option ] ) ||
320 $siteConfig['options_cache'][ $option ] !== get_option( $option )
321 ) {
322 $optionsMismatch = true;
323 break 2;
324 }
325 }
326 }
327 } else {
328 // Flat structure outside the nested loop
329 if (
330 ! isset( $siteConfig['options_cache'][ $opt ] ) ||
331 is_bool( $siteConfig['options_cache'][ $opt ] ) ||
332 $siteConfig['options_cache'][ $opt ] !== get_option( $opt )
333 ) {
334 $optionsMismatch = true;
335 break;
336 }
337 }
338 }
339 } else {
340 $optionsMismatch = true;
341 }
342
343 if (
344 $optionsMismatch ||
345 ( ! array_key_exists( "isEzoicActive", $siteConfig ) || $siteConfig["isEzoicActive"] !== \NitroPack\Integration\Plugin\Ezoic::isActive() ) ||
346 ( ! array_key_exists( "isLateIntegrationInitRequired", $siteConfig ) || $siteConfig["isLateIntegrationInitRequired"] !== nitropack_is_late_integration_init_required() ) ||
347 ( ! array_key_exists( "isDlmActive", $siteConfig ) || $siteConfig["isDlmActive"] !== \NitroPack\Integration\Plugin\DownloadManager::isActive() ) ||
348 ( ! array_key_exists( "isAeliaCurrencySwitcherActive", $siteConfig ) || $siteConfig["isAeliaCurrencySwitcherActive"] !== \NitroPack\Integration\Plugin\AeliaCurrencySwitcher::isActive() ) ||
349 ( ! array_key_exists( "isGeoTargetingWPActive", $siteConfig ) || $siteConfig["isGeoTargetingWPActive"] !== \NitroPack\Integration\Plugin\GeoTargetingWP::isActive() ) ||
350 ( ! array_key_exists( "isWoocommerceActive", $siteConfig ) || $siteConfig["isWoocommerceActive"] !== \NitroPack\Integration\Plugin\WooCommerce::isActive() ) ||
351 ( ! array_key_exists( "isWoocommerceCacheHandlerActive", $siteConfig ) || $siteConfig["isWoocommerceCacheHandlerActive"] !== \NitroPack\Integration\Plugin\WoocommerceCacheHandler::isActive() )
352 ) {
353 if ( ! get_nitropack()->updateCurrentBlogConfig( $siteId, $siteSecret, $blogId ) ) {
354 $errors[] = array(
355 'title' => esc_html__( "NitroPack static config file cannot be updated", 'nitropack' ),
356 'msg' => esc_html__( 'Please make sure that the /wp-content/config-nitropack/ directory is writable and refresh this page.', 'nitropack' ),
357 );
358 }
359 }
360
361 if ( empty( $_COOKIE["nitropack_webhook_sync"] ) || ! $siteConfig["webhookToken"] ) {
362 if ( null !== $nitro = get_nitropack_sdk() ) {
363 try {
364 if ( ! headers_sent() ) {
365 nitropack_setcookie( "nitropack_webhook_sync", "1", time() + 300 ); // Do these checks in 5 minute intervals.
366 }
367 $configWebhook = $nitro->getApi()->getWebhook( "config" );
368 if ( ! empty( $configWebhook ) ) {
369 $query = parse_url( $configWebhook, PHP_URL_QUERY );
370 if ( $query ) {
371 parse_str( $query, $webhookParams );
372 if ( empty( $webhookParams["token"] ) || $webhookParams["token"] != $webhookToken ) {
373 $warnings[] = array(
374 'title' => esc_html__( "Connection problems detected", 'nitropack' ),
375 'msg' => esc_html__( 'Most likely you have used the same API credentials to connect another website (e.g. dev or staging). Click to restore the connection to this site.', 'nitropaack' ),
376 'actions' => '<a id="nitro-restore-connection-btn" class="btn btn-warning">Restore connection</a>',
377 );
378 }
379 }
380 }
381 } catch (\Exception $e) {
382 //Do nothing
383 }
384 }
385 }
386
387 if ( apply_filters( 'nitropack_should_modify_htaccess', false ) && ( empty( $_SERVER["NitroPackHtaccessVersion"] ) || NITROPACK_VERSION != $_SERVER["NitroPackHtaccessVersion"] ) ) {
388 if ( ! nitropack_set_htaccess_rules( true ) ) {
389 $errors[] = array(
390 'title' => esc_html__( "The .htaccess file cannot be modified", 'nitropack' ),
391 'msg' => esc_html__( 'Please make sure that it is writable and refresh this page.', 'nitropack' ),
392 );
393 }
394 }
395 }
396 if ( isset( $nitropack_v1_3_notice_id ) ) {
397 $warnings[] = array(
398 'title' => esc_html__( "NitroPack upgraded to 1.3", 'nitropack' ),
399 'msg' => esc_html__( 'Your new version of NitroPack has a new better way of recaching updated content. However, it is incompatible with the page relationships built by your previous version. Please invalidate your cache manually one-time so that content updates start working with the updated logic.', 'nitropack' ),
400 'dismissibleId' => $nitropack_v1_3_notice_id,
401 'dismissBy' => 'option',
402 );
403 }
404
405 if ( \NitroPack\Integration\Plugin\Cloudflare::isApoActive() && ! \NitroPack\Integration\Plugin\Cloudflare::isApoCacheByDeviceTypeEnabled() ) {
406 $warnings[] = array(
407 'title' => esc_html__( "Cache By Device Type is not activate", 'nitropack' ),
408 'msg' => esc_html__( 'It seems Cache By Device Type is not activate with the Cloudflare APO. It is recommended that you enable it for a more optimized experience.', 'nitropack' ),
409 );
410 }
411 }
412
413 $npPluginNotices = [
414 'error' => $errors,
415 'warning' => $warnings,
416 'info' => $infos
417 ];
418
419 return $npPluginNotices;
420 }
421
422 /**
423 * Display admin notices in the NitroPack -> Dashboard plugin page.
424 *
425 * This function checks if the current user has the necessary capabilities to view the notices.
426 * It renders specific notifications related to hosting information, system, compatibilities and notifications coming from the NitroPack app
427 *
428 * @return void
429 */
430 public function nitropack_display_admin_notices() {
431 if ( ! $this->pass_notification_capabilities() )
432 return;
433
434 $noticesArray = $this->nitropack_plugin_notices();
435 $components = new \NitroPack\WordPress\Settings\Components;
436 foreach ( $noticesArray as $type => $notices ) {
437 foreach ( $notices as $notice ) {
438 $components->render_notification( $notice['msg'], $type, $notice['title'], isset( $notice['actions'] ) ? $notice['actions'] : null, isset( $notice['classes'] ) ? $notice['classes'] : null, isset( $notice['dismissibleId'] ) ? $notice['dismissibleId'] : null, isset( $notice['dismissBy'] ) ? $notice['dismissBy'] : null );
439 }
440 }
441 //render app notifications
442 $this->render_app_notifications();
443 }
444
445 /**
446 * Render notifications coming from notifications.json file such as ones from the NitroPack app.
447 *
448 * @return void
449 */
450 public function render_app_notifications() {
451 $components = new \NitroPack\WordPress\Settings\Components();
452 $app_notifications = AppNotifications::getInstance();
453 foreach ( $app_notifications->get( 'system' ) as $notification ) {
454 $msg = $notification['message'];
455 $type = 'info';
456 $title = '';
457
458 if ( ! empty( $notification['type'] ) ) {
459 $type = $notification['type'];
460 }
461 if ( ! empty( $notification['message_details']['title'] ) ) {
462 $title = $notification['message_details']['title'];
463 }
464 if ( ! empty( $notification['message_details']['message'] ) ) {
465 $msg = $notification['message_details']['message'];
466 }
467
468 $components->render_notification( $msg, $type, $title, '', [ 'app-notification' ], $notification['id'], 'transient', $notification );
469 }
470 }
471 /**
472 * Prints a hosting notice for NitroPack.
473 *
474 * @return void
475 */
476 private function nitropack_print_hosting_notice() {
477
478 $hostingNoticeFile = nitropack_get_hosting_notice_file();
479 if ( ! get_nitropack()->isConnected() || file_exists( $hostingNoticeFile ) )
480 return;
481
482 $documentedHostingSetups = array(
483 "flywheel" => array(
484 "name" => "Flywheel",
485 "helpUrl" => "https://getflywheel.com/wordpress-support/how-to-enable-wp_cache/"
486 ),
487 "cloudways" => array(
488 "name" => "Cloudways",
489 "helpUrl" => "https://support.nitropack.io/hc/en-us/articles/360060916674-Cloudways-Hosting-Configuration-for-NitroPack"
490 )
491 );
492
493 $siteConfig = nitropack_get_site_config();
494
495 if ( $siteConfig && ! empty( $siteConfig["hosting"] ) && array_key_exists( $siteConfig["hosting"], $documentedHostingSetups ) ) {
496
497 $hostingInfo = $documentedHostingSetups[ $siteConfig["hosting"] ];
498 $showNotice = true;
499 if ( $siteConfig["hosting"] == "flywheel" && defined( "WP_CACHE" ) && WP_CACHE ) {
500 $showNotice = false;
501 }
502
503 if ( $showNotice ) {
504 $components = new \NitroPack\WordPress\Settings\Components;
505 $components->render_notification( esc_html__( "Please follow the instructions in order to make sure that everything works correctly.", 'nitropack' ), 'info',
506 sprintf( esc_html__( 'It looks like you are hosted on %s', 'nitropack' ), $hostingInfo['name'] ),
507 '<a href="' . $hostingInfo["helpUrl"] . '" target="_blank" class="btn btn-info btn-ghost">' . esc_html__( 'Read Instructions', 'nitropack' ) . '</a>',
508 [ 'hosting-notice' ], 'hosting-' . $siteConfig["hosting"], 'option' );
509 }
510 }
511 }
512 /**
513 * Prints a WooCommerce notice for NitroPack across WordPress admin
514 * @return void
515 */
516 private function nitropack_print_woocommerce_notice() {
517 if ( get_nitropack()->isConnected() ) {
518 if ( class_exists( 'WooCommerce' ) ) {
519 $np_notices = get_option( 'nitropack-dismissed-notices', [] );
520 $woocommerce_notice = in_array( 'WooCommerce', $np_notices, true ) ? true : false;
521
522 if ( ! $woocommerce_notice ) {
523 $components = new \NitroPack\WordPress\Settings\Components;
524 $components->render_notification( __( 'Your <strong>account</strong>, <strong>cart</strong>, and <strong>checkout</strong> pages are automatically excluded from optimization.', 'nitropack' ),
525 'success',
526 esc_html__( 'WooCommerce detected', 'nitropack' ),
527 '<a class="btn btn-secondary" href="' . admin_url( 'admin.php?page=nitropack' ) . '">' . esc_html__( 'Settings', 'nitropack' ) . '</a>',
528 [ 'woocommerce-notice' ],
529 'WooCommerce', 'option' );
530 }
531 }
532 }
533 }
534
535 public function admin_bar_notices_counter() {
536 if ( ! $this->pass_notification_capabilities() )
537 return;
538
539 $notices = $this->nitropack_plugin_notices();
540
541 $numberOfPluginErrors = 0;
542 $numberOfPluginWarnings = 0;
543 $notificationCount = 0;
544 foreach ( array( "warning", "error", "info" ) as $type ) {
545
546 foreach ( $notices[ $type ] as $notice ) {
547
548 if ( ! empty( $notice['dismissibleId'] ) ) {
549 switch ( $type ) {
550 case "error":
551 $numberOfPluginErrors++;
552 break;
553 case "warning":
554 $numberOfPluginWarnings++;
555 break;
556 case "info":
557 $notificationCount++;
558 break;
559 }
560 }
561
562 }
563 }
564
565 /* Notifications from the app */
566 $app_notifications = AppNotifications::getInstance();
567 foreach ( $app_notifications->get( 'system' ) as $notification ) {
568
569 if ( ! empty( $notification['id'] ) ) {
570
571 /* Don't count if dismissed by transient and the time has passed */
572 $notice = get_transient( $notification['id'] );
573 if ( ! empty( $notice ) && ( $notice && time() < $notice ) ) {
574 continue;
575 }
576
577 if ( ! empty( $notification['type'] ) ) {
578 switch ( $notification['type'] ) {
579 case 'error':
580 $numberOfPluginErrors++;
581 break;
582 case 'warning':
583 $numberOfPluginWarnings++;
584 break;
585 case 'info':
586 $notificationCount++;
587 break;
588 }
589 } else {
590 $notificationCount++;
591 }
592 }
593 }
594
595 $numberOfPluginIssues = $numberOfPluginErrors + $numberOfPluginWarnings;
596
597 if ( $numberOfPluginErrors > 0 ) {
598 $pluginStatus = 'error';
599 } else if ( $numberOfPluginWarnings > 0 ) {
600 $pluginStatus = 'warning';
601 } else {
602 $pluginStatus = 'ok';
603 }
604 $data = [ 'issues' => $numberOfPluginIssues, 'status' => $pluginStatus, 'errors' => $numberOfPluginErrors, 'warnings' => $numberOfPluginWarnings, 'notifications' => $notificationCount ];
605
606 return $data;
607 }
608 /**
609 * Checks if the user has capabilities to manage options - administrators typically have this capability.
610 * @return void|bool
611 */
612 private function pass_notification_capabilities() {
613 if ( ! current_user_can( 'manage_options' ) )
614 return;
615 else {
616 return true;
617 }
618 }
619
620 public function test_mode_notification_html() {
621 $components = new \NitroPack\WordPress\Settings\Components;
622 $components->render_notification( 'Visitors are accessing your unoptimized pages. Make sure to disable it once you are done testing.', 'warning', 'Test Mode Enabled', false, [ 'test-mode' ] );
623 }
624 public function nitropack_safemode_notification() {
625 nitropack_verify_ajax_nonce( $_REQUEST );
626 $this->test_mode_notification_html();
627 wp_die();
628 }
629
630 /* Dismiss notification by using set_transient -> temporary dismissal with auto-expiry */
631 public function nitropack_dismiss_notification_by_transient() {
632 if ( ! $this->pass_notification_capabilities() ) {
633 wp_die( __( 'You do not have sufficient permissions.' ) );
634 }
635
636 if ( empty( $_POST['notification_id'] ) ) {
637 wp_send_json_error( [ 'message' => __( 'Missing notification ID.' ) ] );
638 }
639
640 nitropack_verify_ajax_nonce( $_REQUEST );
641
642 $notification_id = $_POST['notification_id'];
643 $notification_end = $_POST['notification_end'];
644 $midpoint = get_date_midpoint( $notification_end );
645 $notification_end = strtotime( $notification_end ) - time();
646 $transient_status = set_transient( $notification_id, $midpoint, $notification_end );
647
648 nitropack_json_and_exit( array(
649 "transient_status" => $transient_status,
650 ) );
651 }
652
653 /**
654 * Handles the dismissal of a notification permanently by updating nitropack-dismissed-notices option in the database.
655 *
656 * @return void Outputs a JSON response and terminates the script execution.
657 */
658
659 public function nitropack_dismiss_permanently_notification() {
660 if ( ! $this->pass_notification_capabilities() ) {
661 wp_send_json_error( [ 'message' => __( 'You do not have sufficient permissions.' ) ] );
662 }
663
664 if ( empty( $_POST['notification_id'] ) ) {
665 wp_send_json_error( [ 'message' => __( 'Missing notification ID.' ) ] );
666 }
667
668 nitropack_verify_ajax_nonce( $_REQUEST );
669
670 $notification_id = sanitize_text_field( wp_unslash( $_POST['notification_id'] ) );
671 $notices = get_option( 'nitropack-dismissed-notices', [] );
672
673 if ( ! in_array( $notification_id, $notices, true ) ) {
674 $notices[] = $notification_id;
675 update_option( 'nitropack-dismissed-notices', $notices );
676 }
677
678 wp_send_json_success();
679 }
680
681 /**
682 * Moves existing dismissed notices to the new dismissed option as an array.
683 *
684 * Notices being migrated:
685 * - `nitropack-wcNotice` (mapped to `WooCommerce`)
686 * - `nitropack-noticeOptimizeCPT` (mapped to `OptimizeCPT`)
687 *
688 * @return void
689 */
690
691 public function move_existing_notices() {
692 $existing_notices = [ 'nitropack-wcNotice' => 'WooCommerce', 'nitropack-noticeOptimizeCPT' => 'OptimizeCPT' ];
693 foreach ( $existing_notices as $notice => $new_notice ) {
694 if ( get_option( $notice ) ) {
695 $notices = get_option( 'nitropack-dismissed-notices', [] );
696 if ( ! in_array( $notice, $notices, true ) ) {
697 $notices[] = $new_notice;
698 update_option( 'nitropack-dismissed-notices', $notices );
699 }
700 delete_option( $notice );
701 }
702 }
703 }
704 /**
705 * Deactivates a conflicting plugin from NitroPack.
706 *
707 * It verifies the nonce for security and checks if the specified plugin is in the list of conflicting plugins
708 * and finally deactivates it if it is active.
709 *
710 * @return void Outputs a JSON response indicating success or failure.
711 */
712 public function nitropack_conflict_plugin_deactivate() {
713 if ( ! $this->pass_notification_capabilities() ) {
714 wp_send_json_error( [ 'message' => __( 'You do not have sufficient permissions.' ) ] );
715 }
716
717 if ( empty( $_POST['plugin'] ) ) {
718 wp_send_json_error( [ 'message' => __( 'Missing plugin.' ) ] );
719 }
720 $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
721
722 if ( empty( $_POST['plugin_name'] ) ) {
723 wp_send_json_error( [ 'message' => __( 'Missing plugin name.' ) ] );
724 }
725 $plugin_name = sanitize_text_field( wp_unslash( $_POST['plugin_name'] ) );
726
727 nitropack_verify_ajax_nonce( $_REQUEST );
728
729 // Check if the plugin is in the list of conflicting plugins for extra security measures.
730 $conflictingPlugins = \NitroPack\WordPress\ConflictingPlugins::getInstance();
731 $conflictingPlugins_list = $conflictingPlugins->nitropack_get_conflicting_plugins();
732 $plugin_found = false;
733 foreach ( $conflictingPlugins_list as $conflict_plugin ) {
734 if ( $conflict_plugin['plugin'] === $plugin ) {
735 $plugin_found = true;
736 break;
737 }
738 }
739 if ( ! $plugin_found ) {
740 wp_send_json_error( [ 'message' => __( 'Plugin not found in the list of conflicting plugins.' ) ] );
741 }
742
743 if ( is_plugin_active( $plugin ) ) {
744 deactivate_plugins( $plugin );
745 if ( ! is_plugin_active( $plugin ) ) {
746 wp_send_json_success( [ 'message' => sprintf( esc_html__( '%s deactivated successfully.', 'nitropack' ), $plugin_name ) ] );
747 } else {
748 wp_send_json_error( [ 'message' => __( 'Failed to deactivate the plugin.' ) ] );
749 }
750 } else {
751 wp_send_json_error( [ 'message' => sprintf( esc_html__( '%s is not active.', 'nitropack' ), $plugin_name ) ] );
752 }
753 }
754 }
755