PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.19.0
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.19.0
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / classes / WordPress / Settings / SystemReport.php
nitropack / classes / WordPress / Settings Last commit date
AutoPurge.php 4 months ago BeaverBuilder.php 4 months ago CPTOptimization.php 4 months ago CacheWarmup.php 4 months ago CartCache.php 4 months ago Components.php 4 months ago EditorClearCache.php 4 months ago GeneratePreview.php 7 months ago HTMLCompression.php 4 months ago Logger.php 4 months ago OptimizationLevel.php 4 months ago Optimizations.php 4 months ago PurgeCache.php 4 months ago Shortcodes.php 4 months ago StockRefresh.php 4 months ago Subscription.php 4 months ago SystemReport.php 4 months ago TestMode.php 4 months ago
SystemReport.php
374 lines
1 <?php
2 namespace NitroPack\WordPress\Settings;
3 use \NitroPack\SDK\Api\ResponseStatus;
4
5 /**
6 * Class System Report used in NitroPack
7 */
8 class SystemReport {
9 private static $instance = null;
10 /**
11 * Singleton instance. Avoids multiple instances.
12 * @return SystemReport
13 */
14 public static function getInstance() {
15 if ( null === self::$instance ) {
16 self::$instance = new self();
17 }
18 return self::$instance;
19 }
20
21 public function __construct() {
22 add_action( 'wp_ajax_nitropack_generate_report', [ $this, 'nitropack_generate_report' ] );
23 }
24
25 /**
26 * Generates a system report based on selected options and outputs it as a downloadable file.
27 */
28 public function nitropack_generate_report() {
29 nitropack_verify_ajax_nonce( $_REQUEST );
30
31 $np_diag_functions = array(
32 'general-info-status' => $this->get_general_info(),
33 'active-plugins-status' => $this->get_active_plugins(),
34 'conflicting-plugins-status' => $this->get_conflicting_plugins(),
35 'user-config-status' => $this->get_user_config(),
36 'dir-info-status' => $this->get_dir_info(),
37 'getexternalcache' => $this->detect_third_party_cache()
38 );
39 try {
40 $options = ! empty( $_POST["toggled"] ) ? $_POST["toggled"] : NULL;
41
42 if ( $options !== NULL ) {
43 $diag_data = array( 'report-time-stamp' => date( "Y-m-d H:i:s" ) );
44 foreach ( $options as $func_name => $func_allowed ) {
45 if ( (boolean) $func_allowed ) {
46 $diag_data[ $func_name ] = $np_diag_functions[ $func_name ];
47 }
48 }
49 $str = json_encode( $diag_data, JSON_PRETTY_PRINT );
50 $filename = 'nitropack_diag_file.txt';
51 nitropack_header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
52 nitropack_header( "Content-Type: text/plain" );
53 nitropack_header( "Content-Length: " . strlen( $str ) );
54 echo $str;
55 wp_die();
56 }
57 } catch (\Exception $e) {
58 wp_send_json_error( __( 'Error generating report: ', 'nitropack' ) . $e->getMessage() );
59 }
60 }
61
62 private function helper_trailingslashit( $string ) {
63 return rtrim( $string, '/\\' ) . '/';
64 }
65 /**
66 * Compares the constructed webhook URL with the stored one in NitroPack
67 *
68 * @param \NitroPack\SDK\Nitropack $nitro_sdk The NitroPack SDK instance.
69 * @return string Result of the comparison.
70 */
71 private function compare_webhooks( $nitro_sdk ) {
72 try {
73 $siteConfig = nitropack_get_site_config();
74 if ( ! empty( $siteConfig['siteId'] ) ) {
75 $WHToken = nitropack_generate_webhook_token( $siteConfig['siteId'] );
76 $constructedWH = new \NitroPack\Url\Url( strtolower( get_home_url() ) ) . '?nitroWebhook=config&token=' . $WHToken;
77 $storedWH = $nitro_sdk->getApi()->getWebhook( "config" );
78 $matchResult = ( $constructedWH == $storedWH ) ? __( 'OK', 'nitropack' ) : __( 'Warning: Webhooks do not match this site', 'nitropack' );
79 } else {
80 $debugMsg = empty( $_SERVER["HTTP_HOST"] ) ? "HTTP_HOST is not defined. " : "";
81 $debugMsg .= empty( $_SERVER["REQUEST_URI"] ) ? "REQUEST_URI is not defined. " : "";
82 $debugMsg .= empty( $debugMsg ) ? 'URL used to match config was: ' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] : "";
83 $matchResult = __( 'Site config cannot be found, because ', 'nitropack' ) . $debugMsg;
84 }
85 return $matchResult;
86 } catch (\Exception $e) {
87 return $e->getMessage();
88 }
89 }
90 /**
91 * Polls the NitroPack API and returns a human-readable status message.
92 *
93 * @param \NitroPack\SDK\Nitropack $nitro_sdk The NitroPack SDK instance.
94 * @return string The status message based on the API response.
95 */
96 private function poll_api( $nitro_sdk ) {
97 $pollResult = array(
98 ResponseStatus::OK => __( 'OK', 'nitropack' ),
99 ResponseStatus::ACCEPTED => __( 'OK', 'nitropack' ),
100 ResponseStatus::BAD_REQUEST => __( 'Bad request.', 'nitropack' ),
101 ResponseStatus::PAYMENT_REQUIRED => __( 'Payment required. Please, contact NP support for details.', 'nitropack' ),
102 ResponseStatus::FORBIDDEN => __( 'Site disabled. Please, contact NP support for details.', 'nitropack' ),
103 ResponseStatus::NOT_FOUND => __( 'URL used for the API poll request returned 404. Please ignore this.', 'nitropack' ),
104 ResponseStatus::CONFLICT => __( 'Conflict. There is another operation, which prevents accepting optimization requests at the moment. Please, contact NP support for details.', 'nitropack' ),
105 ResponseStatus::RUNTIME_ERROR => __( 'Runtime error.', 'nitropack' ),
106 ResponseStatus::SERVICE_UNAVAILABLE => __( 'Service unavailable.', 'nitropack' ),
107 ResponseStatus::UNKNOWN => __( 'Unknown.', 'nitropack' )
108 );
109
110 try {
111 $referer = isset( $_SERVER["HTTP_REFERER"] ) ? $_SERVER["HTTP_REFERER"] : '';
112 $apiResponseCode = $nitro_sdk->getApi()->getCache( get_home_url(), __( 'NitroPack Diagnostic Agent', 'nitropack' ), array(), false, 'default', $referer )->getStatus();
113 return $pollResult[ $apiResponseCode ];
114 } catch (\Exception $e) {
115 return 'Error: ' . $e->getMessage();
116 }
117
118 }
119
120 private function backlog_status( $nitro_sdk ) {
121 return $nitro_sdk->backlog->exists() ? 'Warning' : 'OK';
122 }
123 /**
124 * Gathers general information about the NitroPack installation and environment.
125 *
126 * @return array An associative array containing various pieces of information.
127 */
128 private function get_general_info() {
129 global $wp_version;
130 if ( null !== $nitro = get_nitropack_sdk() ) {
131 $probe_result = "OK";
132 try {
133 $nitro->fetchConfig();
134 } catch (\Exception $e) {
135 $probe_result = __( 'Error: ', 'nitropack' ) . $e->getMessage();
136 }
137 } else {
138 $probe_result = __( 'Error: Cannot get an SDK instance', 'nitropack' );
139 }
140
141 $third_party_residual_cache = $this->detect_third_party_cache();
142
143 $info = array(
144 'Nitro_WP_version' => ! empty( $wp_version ) ? $wp_version : get_bloginfo( 'version' ),
145 'Nitro_Version' => defined( 'NITROPACK_VERSION' ) ? NITROPACK_VERSION : __( 'Undefined', 'nitropack' ),
146 'Nitro_SDK_Connection' => $probe_result,
147 'Nitro_API_Polling' => $nitro ? $this->poll_api( $nitro ) : __( 'Error: Cannot get an SDK instance', 'nitropack' ),
148 'Nitro_SDK_Version' => defined( 'NitroPack\SDK\Nitropack::VERSION' ) ? \NitroPack\SDK\Nitropack::VERSION : __( 'Undefined', 'nitropack' ),
149 'Nitro_WP_Cache' => defined( 'WP_CACHE' ) ? ( WP_CACHE ? __( 'OK for drop-in', 'nitropack' ) : __( 'Turned off', 'nitropack' ) ) : __( 'Undefined', 'nitropack' ),
150 'Advanced_Cache_Version' => defined( 'NITROPACK_ADVANCED_CACHE_VERSION' ) ? NITROPACK_ADVANCED_CACHE_VERSION : __( 'Undefined', 'nitropack' ),
151 'Nitro_Absolute_Path' => defined( 'ABSPATH' ) ? ABSPATH : __( 'Undefined', 'nitropack' ),
152 'Nitro_Plugin_Directory' => defined( 'NITROPACK_PLUGIN_DIR' ) ? NITROPACK_PLUGIN_DIR : dirname( __FILE__ ),
153 'Nitro_Data_Directory' => defined( 'NITROPACK_DATA_DIR' ) ? NITROPACK_DATA_DIR : __( 'Undefined', 'nitropack' ),
154 'Nitro_Plugin_Data_Directory' => defined( 'NITROPACK_PLUGIN_DATA_DIR' ) ? NITROPACK_PLUGIN_DATA_DIR : __( 'Undefined', 'nitropack' ),
155 'Nitro_Config_File' => defined( 'NITROPACK_CONFIG_FILE' ) ? NITROPACK_CONFIG_FILE : __( 'Undefined', 'nitropack' ),
156 'Nitro_Backlog_File_Status' => $nitro ? $this->backlog_status( $nitro ) : __( 'Error: Cannot get an SDK instance', 'nitropack' ),
157 'Nitro_Webhooks' => $nitro ? $this->compare_webhooks( $nitro ) : __( 'Error: Cannot get an SDK instance', 'nitropack' ),
158 'Nitro_Connectivity_Requirements' => nitropack_check_func_availability( 'stream_socket_client' ) ? __( 'OK', 'nitropack' ) : __( 'Warning: "stream_socket_client" function is disabled.', 'nitropack' ),
159 'Residual_Cache_Found_For' => $third_party_residual_cache,
160 );
161
162 if ( defined( "NITROPACK_VERSION" ) && defined( "NITROPACK_ADVANCED_CACHE_VERSION" ) && NITROPACK_VERSION == NITROPACK_ADVANCED_CACHE_VERSION && nitropack_is_dropin_cache_allowed() ) {
163 $info['Nitro_Cache_Method'] = 'drop-in';
164 } elseif ( defined( 'EZOIC_INTEGRATION_VERSION' ) ) {
165 $info['Nitro_Cache_Method'] = 'plugin-ezoic';
166 } else {
167 $info['Nitro_Cache_Method'] = 'plugin';
168 }
169
170 return $info;
171 }
172
173 /**
174 * Retrieves a list of active plugins and their versions.
175 *
176 * @return array An associative array where keys are plugin names and values are their versions.
177 */
178 private function get_active_plugins() {
179
180 $plugins = array();
181 $raw_installed_list = get_plugins();
182 $raw_active_list = get_option( 'active_plugins' );
183 foreach ( $raw_installed_list as $pkey => $pval ) {
184 if ( in_array( $pkey, $raw_active_list ) ) {
185 $plugins[ $pval['Name'] ] = $pval['Version'];
186 }
187 }
188
189 return $plugins;
190 }
191
192 /** Retrieves the contents of the NitroPack configuration file - config.json in wp-content/config-[hash]-nitropack/.
193 *
194 * @return mixed The contents of the configuration file or an error message.
195 */
196 private function get_user_config() {
197 if ( defined( 'NITROPACK_CONFIG_FILE' ) ) {
198 if ( file_exists( NITROPACK_CONFIG_FILE ) ) {
199 $info = json_decode( file_get_contents( NITROPACK_CONFIG_FILE ) );
200 if ( ! $info ) {
201 $info = __( 'Config found, but unable to get contents.', 'nitropack' );
202 }
203 } else {
204 $info = __( 'Config file not found.', 'nitropack' );
205 }
206 } else {
207 $info = __( 'Config file constant is not defined.', 'nitropack' );
208 }
209
210 return $info;
211 }
212
213 /**[p]
214 * Gathers information about specific directories related to NitroPack.
215 *
216 * @return array An associative array containing the status of various directories.
217 */
218 private function get_dir_info() {
219 $siteConfig = nitropack_get_site_config();
220 $siteID = $siteConfig['siteId'];
221 // DoI = Directories of Interest
222 $DoI = array(
223 'WP_Content_Dir_Writable' => defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR : ( defined( 'ABSPATH' ) ? ABSPATH . '/wp-content' : __( 'Undefined', 'nitropack' ) ),
224 'Nitro_Data_Dir_Writable' => defined( 'NITROPACK_DATA_DIR' ) ? NITROPACK_DATA_DIR : $this->helper_trailingslashit( WP_CONTENT_DIR ) . 'nitropack',
225 'Nitro_siteID_Dir_Writable' => defined( 'NITROPACK_DATA_DIR' ) ? NITROPACK_DATA_DIR . "/$siteID" : $this->helper_trailingslashit( WP_CONTENT_DIR ) . "nitropack/$siteID",
226 'Nitro_Plugin_Dir_Writable' => defined( 'NITROPACK_PLUGIN_DIR' ) ? NITROPACK_PLUGIN_DIR : dirname( __FILE__ ),
227 'Nitro_Plugin_Data_Dir_Writable' => defined( 'NITROPACK_PLUGIN_DATA_DIR' ) ? NITROPACK_PLUGIN_DATA_DIR : $this->helper_trailingslashit( WP_CONTENT_DIR ) . 'nitropack',
228 );
229
230 $info = array();
231 foreach ( $DoI as $doi_dir => $dpath ) {
232 if ( is_dir( $dpath ) ) {
233 $info[ $doi_dir ] = is_writeable( $dpath ) ? true : false;
234 } else if ( is_file( $dpath ) ) {
235 $info[ $doi_dir ] = $dpath . __( ' is a file not a directory', 'nitropack' );
236 } else {
237 $info[ $doi_dir ] = __( 'Directory not found', 'nitropack' );
238 }
239 }
240 return $info;
241 }
242
243 /**
244 * Retrieves a list of plugins that are known to conflict with NitroPack.
245 *
246 * @return array|string An array of conflicting plugins or a message indicating none were detected.
247 */
248 private function get_conflicting_plugins() {
249 $conflictingPlugins = \NitroPack\WordPress\ConflictingPlugins::getInstance();
250 $info = $conflictingPlugins->nitropack_get_conflicting_plugins();
251 if ( ! empty( $info ) ) {
252 return $info;
253 } else {
254 return $info = __( 'None detected', 'nitropack' );
255 }
256 }
257
258 /**
259 * Detects third-party caching plugins that might conflict with NitroPack.
260 *
261 * @return mixed Information about detected third-party caches or a message indicating none were found.
262 */
263 private function detect_third_party_cache() {
264 $info = \NitroPack\Integration\Plugin\RC::detectThirdPartyCaches();
265 if ( ! empty( $info ) ) {
266 return $info;
267 } else {
268 return $info = __( 'Not found', 'nitropack' );
269 }
270 }
271
272 /**
273 * Summary of diagnostic_settings
274 * @return array{class: string, desc: string, id: string, name: mixed, setting: string[]}
275 */
276 private function diagnostic_settings() {
277 $diagnostic_settings = array(
278 array(
279 'name' => esc_html__( 'Include NitroPack info (version, methods, environment)', 'nitropack' ),
280 'desc' => '',
281 'id' => 'general-info-status',
282 'class' => 'diagnostic-option',
283 'setting' => 'include_info'
284 ),
285 array(
286 'name' => esc_html__( 'Include active plugins list', 'nitropack' ),
287 'desc' => '',
288 'id' => 'active-plugins-status',
289 'class' => 'diagnostic-option',
290 'setting' => 'active_plugins'
291 ),
292 array(
293 'name' => esc_html__( 'Include conflicting plugins list', 'nitropack' ),
294 'desc' => '',
295 'id' => 'conflicting-plugins-status',
296 'class' => 'diagnostic-option',
297 'setting' => 'conflicting_plugins'
298 ),
299 array(
300 'name' => esc_html__( 'Include plugin config', 'nitropack' ),
301 'desc' => '',
302 'id' => 'user-config-status',
303 'class' => 'diagnostic-option',
304 'setting' => 'user_conflict'
305 ),
306 array(
307 'name' => esc_html__( 'Include directory status', 'nitropack' ),
308 'desc' => '',
309 'id' => 'dir-info-status',
310 'class' => 'diagnostic-option',
311 'setting' => 'dir_info_status'
312 ),
313 );
314 return $diagnostic_settings;
315 }
316
317 /**
318 * Renders the System Report settings page.
319 */
320 public function render() {
321 ?>
322 <div class="flex">
323 <div class="" style="flex-basis: 80%;">
324 <h3><?php esc_html_e( 'System Info Report', 'nitropack' ); ?></h3>
325 <p><?php esc_html_e( 'This report gives a clear picture of how NitroPack is set up on your site. It checks for anything that might cause problems, like plugins that don’t work well with NitroPack or server issues. If something isn’t working as expected, share this report with support to help them fix it quickly.', 'nitropack' ); ?>
326 </p>
327 </div>
328
329 <div class="ml-auto">
330 <?php $components = new Components();
331 echo $components->render_button( [ 'text' => 'Download', 'type' => null, 'classes' => 'btn btn-secondary', 'icon' => 'download.svg', 'attributes' => [ 'id' => 'gen-report-btn' ] ] );
332 ?>
333
334 </div>
335 </div>
336 <div class="card-body">
337 <div>
338 <div id="accordion-collapse" data-accordion="collapse" class="mt-4" data-active-classes="active"
339 data-inactive-classes="not-active">
340 <div id="accordion-collapse-heading-1" class="text-center">
341 <a class="btn btn-link" data-accordion-target="#accordion-collapse-body-1" aria-expanded="false"
342 aria-controls="accordion-collapse-body-1">
343 <span><?php esc_html_e( 'Customize Report', 'nitropack' ); ?></span>
344 <svg width="9" height="6" data-accordion-icon class="w-3 h-3 rotate-180 shrink-0 icon-right"
345 aria-hidden="false" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none"
346 viewBox="0 0 10 6">
347 <path d="M8.5 5L4.5 1L0.5 5" stroke="#4600CC" stroke-linecap="round" stroke-linejoin="round" />
348 </svg>
349 </a>
350 </div>
351 <div id="accordion-collapse-body-1" class="accordion-body hidden"
352 aria-labelledby="accordion-collapse-heading-1">
353 <div class="options-container">
354 <?php foreach ( $this->diagnostic_settings() as $setting ) : ?>
355 <div class="nitro-option">
356 <div class="nitro-option-main">
357 <h6><?php echo $setting['name']; ?></h6>
358 <label class="inline-flex items-center cursor-pointer ml-auto">
359 <input type="checkbox" value="" id="<?php echo $setting['id']; ?>"
360 class="sr-only peer <?php echo $setting['class']; ?>"
361 name="<?php echo $setting['setting']; ?>" checked>
362 <div class="toggle"></div>
363 </label>
364 </div>
365 </div>
366 <?php endforeach; ?>
367 </div>
368 </div>
369 </div>
370 </div>
371 </div>
372 <?php
373 }
374 }