TrackingSettings
6 years ago
views
6 years ago
AccessSettings.php
6 years ago
Admin.php
6 years ago
AdminSettings.php
6 years ago
AdminSettingsInterface.php
6 years ago
AdvancedSettings.php
6 years ago
ExclusionSettings.php
6 years ago
GeolocationSettings.php
6 years ago
GetStarted.php
6 years ago
Info.php
6 years ago
Marketplace.php
6 years ago
Menu.php
6 years ago
PrivacySettings.php
6 years ago
SafeModeMenu.php
6 years ago
Summary.php
6 years ago
SystemReport.php
6 years ago
TrackingSettings.php
6 years ago
SystemReport.php
1057 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Matomo - free/libre analytics platform |
| 4 | * |
| 5 | * @link https://matomo.org |
| 6 | * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later |
| 7 | * @package matomo |
| 8 | */ |
| 9 | |
| 10 | namespace WpMatomo\Admin; |
| 11 | |
| 12 | use Piwik\CliMulti; |
| 13 | use Piwik\Common; |
| 14 | use Piwik\Container\StaticContainer; |
| 15 | use Piwik\Filesystem; |
| 16 | use Piwik\MetricsFormatter; |
| 17 | use Piwik\Plugins\Diagnostics\Diagnostic\DiagnosticResult; |
| 18 | use Piwik\Plugins\Diagnostics\DiagnosticService; |
| 19 | use Piwik\Plugins\UserCountry\LocationProvider; |
| 20 | use WpMatomo\Bootstrap; |
| 21 | use WpMatomo\Capabilities; |
| 22 | use WpMatomo\Logger; |
| 23 | use WpMatomo\Paths; |
| 24 | use WpMatomo\ScheduledTasks; |
| 25 | use WpMatomo\Settings; |
| 26 | use WpMatomo\Site; |
| 27 | use WpMatomo\Site\Sync as SiteSync; |
| 28 | use WpMatomo\User\Sync as UserSync; |
| 29 | |
| 30 | if ( ! defined( 'ABSPATH' ) ) { |
| 31 | exit; // if accessed directly |
| 32 | } |
| 33 | |
| 34 | class SystemReport { |
| 35 | const NONCE_NAME = 'matomo_troubleshooting'; |
| 36 | const TROUBLESHOOT_SYNC_USERS = 'matomo_troubleshooting_action_site_users'; |
| 37 | const TROUBLESHOOT_SYNC_ALL_USERS = 'matomo_troubleshooting_action_all_users'; |
| 38 | const TROUBLESHOOT_SYNC_SITE = 'matomo_troubleshooting_action_site'; |
| 39 | const TROUBLESHOOT_SYNC_ALL_SITES = 'matomo_troubleshooting_action_all_sites'; |
| 40 | const TROUBLESHOOT_CLEAR_MATOMO_CACHE = 'matomo_troubleshooting_action_clear_matomo_cache'; |
| 41 | const TROUBLESHOOT_ARCHIVE_NOW = 'matomo_troubleshooting_action_archive_now'; |
| 42 | const TROUBLESHOOT_UPDATE_GEOIP_DB = 'matomo_troubleshooting_action_update_geoipdb'; |
| 43 | const TROUBLESHOOT_CLEAR_LOGS = 'matomo_troubleshooting_action_clear_logs'; |
| 44 | |
| 45 | private $not_compatible_plugins = array( |
| 46 | 'background-manager/background-manager.php', // Uses an old version of Twig and plugin is no longer maintained. |
| 47 | ); |
| 48 | |
| 49 | private $valid_tabs = array( 'troubleshooting' ); |
| 50 | |
| 51 | /** |
| 52 | * @var Settings |
| 53 | */ |
| 54 | private $settings; |
| 55 | |
| 56 | /** |
| 57 | * @var Logger |
| 58 | */ |
| 59 | private $logger; |
| 60 | |
| 61 | public function __construct( Settings $settings ) { |
| 62 | $this->settings = $settings; |
| 63 | $this->logger = new Logger(); |
| 64 | } |
| 65 | |
| 66 | public function get_not_compatible_plugins() { |
| 67 | return $this->not_compatible_plugins; |
| 68 | } |
| 69 | |
| 70 | private function execute_troubleshoot_if_needed() { |
| 71 | if ( ! empty( $_POST ) |
| 72 | && is_admin() |
| 73 | && check_admin_referer( self::NONCE_NAME ) |
| 74 | && current_user_can( Capabilities::KEY_SUPERUSER ) ) { |
| 75 | if ( ! empty( $_POST[ self::TROUBLESHOOT_ARCHIVE_NOW ] ) ) { |
| 76 | Bootstrap::do_bootstrap(); |
| 77 | $scheduled_tasks = new ScheduledTasks( $this->settings ); |
| 78 | |
| 79 | try { |
| 80 | $errors = $scheduled_tasks->archive( $force = true, $throw_exception = false ); |
| 81 | } catch (\Exception $e) { |
| 82 | echo '<div class="error"><p>' . esc_html__('Matomo Archive Error', 'matomo') . ': '. esc_html(matomo_anonymize_value($e->getMessage() . ' =>' . $this->logger->get_readable_trace($e))) . '</p></div>'; |
| 83 | throw $e; |
| 84 | } |
| 85 | |
| 86 | if ( ! empty( $errors ) ) { |
| 87 | echo '<div class="notice notice-warning"><p>Matomo Archive Warnings: '; |
| 88 | foreach ($errors as $error) { |
| 89 | echo nl2br(esc_html(matomo_anonymize_value(var_export($error, 1)))); |
| 90 | echo '<br/>'; |
| 91 | } |
| 92 | echo '</p></div>'; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | if ( ! empty( $_POST[ self::TROUBLESHOOT_CLEAR_MATOMO_CACHE ] ) ) { |
| 97 | $paths = new Paths(); |
| 98 | $paths->clear_cache_dir(); |
| 99 | // we first delete the cache dir manually just in case there's something |
| 100 | // going wrong with matomo and bootstrapping would not even be possible. |
| 101 | Bootstrap::do_bootstrap(); |
| 102 | Filesystem::deleteAllCacheOnUpdate(); |
| 103 | } |
| 104 | |
| 105 | if ( ! empty( $_POST[ self::TROUBLESHOOT_UPDATE_GEOIP_DB ] ) ) { |
| 106 | $scheduled_tasks = new ScheduledTasks( $this->settings ); |
| 107 | $scheduled_tasks->update_geo_ip2_db(); |
| 108 | } |
| 109 | |
| 110 | if ( ! empty( $_POST[ self::TROUBLESHOOT_CLEAR_LOGS ] ) ) { |
| 111 | $this->logger->clear_logged_exceptions(); |
| 112 | } |
| 113 | |
| 114 | if ( ! $this->settings->is_network_enabled() || ! is_network_admin() ) { |
| 115 | if ( ! empty( $_POST[ self::TROUBLESHOOT_SYNC_USERS ] ) ) { |
| 116 | $sync = new UserSync(); |
| 117 | $sync->sync_current_users(); |
| 118 | } |
| 119 | if ( ! empty( $_POST[ self::TROUBLESHOOT_SYNC_SITE ] ) ) { |
| 120 | $sync = new SiteSync( $this->settings ); |
| 121 | $sync->sync_current_site(); |
| 122 | } |
| 123 | } |
| 124 | if ( $this->settings->is_network_enabled() ) { |
| 125 | if ( ! empty( $_POST[ self::TROUBLESHOOT_SYNC_ALL_SITES ] ) ) { |
| 126 | $sync = new SiteSync( $this->settings ); |
| 127 | $sync->sync_all(); |
| 128 | } |
| 129 | if ( ! empty( $_POST[ self::TROUBLESHOOT_SYNC_ALL_USERS ] ) ) { |
| 130 | $sync = new UserSync(); |
| 131 | $sync->sync_all(); |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | public function show() { |
| 138 | $this->execute_troubleshoot_if_needed(); |
| 139 | |
| 140 | $settings = $this->settings; |
| 141 | |
| 142 | $matomo_active_tab = ''; |
| 143 | if ( isset( $_GET['tab'] ) && in_array( $_GET['tab'], $this->valid_tabs, true ) ) { |
| 144 | $matomo_active_tab = $_GET['tab']; |
| 145 | } |
| 146 | |
| 147 | $matomo_tables = array(); |
| 148 | if ( empty( $matomo_active_tab ) ) { |
| 149 | $matomo_tables = array( |
| 150 | array( |
| 151 | 'title' => 'Matomo', |
| 152 | 'rows' => $this->get_matomo_info(), |
| 153 | 'has_comments' => true, |
| 154 | ), |
| 155 | array( |
| 156 | 'title' => 'WordPress', |
| 157 | 'rows' => $this->get_wordpress_info(), |
| 158 | 'has_comments' => true, |
| 159 | ), |
| 160 | array( |
| 161 | 'title' => 'WordPress Plugins', |
| 162 | 'rows' => $this->get_plugins_info(), |
| 163 | 'has_comments' => true, |
| 164 | ), |
| 165 | array( |
| 166 | 'title' => 'Server', |
| 167 | 'rows' => $this->get_server_info(), |
| 168 | 'has_comments' => true, |
| 169 | ), |
| 170 | array( |
| 171 | 'title' => 'Database', |
| 172 | 'rows' => $this->get_db_info(), |
| 173 | 'has_comments' => true, |
| 174 | ), |
| 175 | array( |
| 176 | 'title' => 'Browser', |
| 177 | 'rows' => $this->get_browser_info(), |
| 178 | 'has_comments' => false, |
| 179 | ), |
| 180 | ); |
| 181 | } |
| 182 | $matomo_tables = apply_filters('matomo_systemreport_tables', $matomo_tables); |
| 183 | $matomo_tables = $this->add_errors_first( $matomo_tables ); |
| 184 | $matomo_has_warning_and_no_errors = $this->has_only_warnings_no_error( $matomo_tables ); |
| 185 | |
| 186 | $matomo_has_exception_logs = $this->logger->get_last_logged_entries(); |
| 187 | |
| 188 | include dirname( __FILE__ ) . '/views/systemreport.php'; |
| 189 | } |
| 190 | |
| 191 | private function has_only_warnings_no_error( $report_tables ) { |
| 192 | $has_warning = false; |
| 193 | $has_error = false; |
| 194 | foreach ( $report_tables as $report_table ) { |
| 195 | foreach ( $report_table['rows'] as $row ) { |
| 196 | if ( ! empty( $row['is_error'] ) ) { |
| 197 | $has_error = true; |
| 198 | } |
| 199 | if ( ! empty( $row['is_warning'] ) ) { |
| 200 | $has_warning = true; |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | return $has_warning && ! $has_error; |
| 206 | } |
| 207 | |
| 208 | private function add_errors_first( $report_tables ) { |
| 209 | $errors = array( |
| 210 | 'title' => 'Errors', |
| 211 | 'rows' => array(), |
| 212 | 'has_comments' => true, |
| 213 | ); |
| 214 | foreach ( $report_tables as $report_table ) { |
| 215 | foreach ( $report_table['rows'] as $row ) { |
| 216 | if ( ! empty( $row['is_error'] ) ) { |
| 217 | $errors['rows'][] = $row; |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | if ( ! empty( $errors['rows'] ) ) { |
| 223 | array_unshift( $report_tables, $errors ); |
| 224 | } |
| 225 | |
| 226 | return $report_tables; |
| 227 | } |
| 228 | |
| 229 | private function check_file_exists_and_writable( $rows, $path_to_check, $title, $required ) { |
| 230 | $file_exists = file_exists( $path_to_check ); |
| 231 | $file_readable = is_readable( $path_to_check ); |
| 232 | $file_writable = is_writable( $path_to_check ); |
| 233 | $comment = '"' . $path_to_check . '" '; |
| 234 | if ( ! $file_exists ) { |
| 235 | $comment .= sprintf( esc_html__( '%s does not exist. ', 'matomo' ), $title ); |
| 236 | } |
| 237 | if ( ! $file_readable ) { |
| 238 | $comment .= sprintf( esc_html__( '%s is not readable. ', 'matomo' ), $title ); |
| 239 | } |
| 240 | if ( ! $file_writable ) { |
| 241 | $comment .= sprintf( esc_html__( '%s is not writable. ', 'matomo' ), $title ); |
| 242 | } |
| 243 | |
| 244 | $rows[] = array( |
| 245 | 'name' => sprintf( esc_html__( '%s exists and is writable.', 'matomo' ), $title ), |
| 246 | 'value' => $file_exists && $file_readable && $file_writable ? esc_html__( 'Yes', 'matomo' ) : esc_html__( 'No', 'matomo' ), |
| 247 | 'comment' => $comment, |
| 248 | 'is_error' => $required && ( ! $file_exists || ! $file_readable ), |
| 249 | 'is_warning' => ! $required && ( ! $file_exists || ! $file_readable ), |
| 250 | ); |
| 251 | |
| 252 | return $rows; |
| 253 | } |
| 254 | |
| 255 | private function get_matomo_info() { |
| 256 | $rows = array(); |
| 257 | |
| 258 | $plugin_data = get_plugin_data( MATOMO_ANALYTICS_FILE, $markup = false, $translate = false ); |
| 259 | |
| 260 | $rows[] = array( |
| 261 | 'name' => esc_html__( 'Matomo Plugin Version', 'matomo' ), |
| 262 | 'value' => $plugin_data['Version'], |
| 263 | 'comment' => '', |
| 264 | ); |
| 265 | |
| 266 | $paths = new Paths(); |
| 267 | $path_config_file = $paths->get_config_ini_path(); |
| 268 | $rows = $this->check_file_exists_and_writable( $rows, $path_config_file, 'Config', true ); |
| 269 | |
| 270 | $path_tracker_file = $paths->get_matomo_js_upload_path(); |
| 271 | $rows = $this->check_file_exists_and_writable( $rows, $path_tracker_file, 'JS Tracker', false ); |
| 272 | |
| 273 | $rows[] = array( |
| 274 | 'name' => esc_html__( 'Plugin directories', 'matomo' ), |
| 275 | 'value' => ! empty( $GLOBALS['MATOMO_PLUGIN_DIRS'] ) ? 'Yes' : 'No', |
| 276 | 'comment' => ! empty( $GLOBALS['MATOMO_PLUGIN_DIRS'] ) ? wp_json_encode( $GLOBALS['MATOMO_PLUGIN_DIRS'] ) : '', |
| 277 | ); |
| 278 | |
| 279 | $tmp_dir = $paths->get_tmp_dir(); |
| 280 | |
| 281 | $rows[] = array( |
| 282 | 'name' => esc_html__( 'Tmp directory writable', 'matomo' ), |
| 283 | 'value' => is_writable( $tmp_dir ), |
| 284 | 'comment' => $tmp_dir, |
| 285 | ); |
| 286 | |
| 287 | if ( ! empty( $_SERVER['MATOMO_WP_ROOT_PATH'] ) ) { |
| 288 | $custom_path = rtrim( $_SERVER['MATOMO_WP_ROOT_PATH'], '/' ) . '/wp-load.php'; |
| 289 | $path_exists = file_exists( $custom_path ); |
| 290 | $comment = ''; |
| 291 | if ( ! $path_exists ) { |
| 292 | $comment = 'It seems the path does not point to the WP root directory.'; |
| 293 | } |
| 294 | |
| 295 | $rows[] = array( |
| 296 | 'name' => 'Custom MATOMO_WP_ROOT_PATH', |
| 297 | 'value' => $path_exists, |
| 298 | 'is_error' => ! $path_exists, |
| 299 | 'comment' => $comment, |
| 300 | ); |
| 301 | } |
| 302 | |
| 303 | $report = null; |
| 304 | |
| 305 | if ( ! \WpMatomo::is_safe_mode() ) { |
| 306 | try { |
| 307 | Bootstrap::do_bootstrap(); |
| 308 | /** @var DiagnosticService $service */ |
| 309 | $service = StaticContainer::get( DiagnosticService::class ); |
| 310 | $report = $service->runDiagnostics(); |
| 311 | |
| 312 | $rows[] = array( |
| 313 | 'name' => esc_html__( 'Matomo Version', 'matomo' ), |
| 314 | 'value' => \Piwik\Version::VERSION, |
| 315 | 'comment' => '', |
| 316 | ); |
| 317 | } catch ( \Exception $e ) { |
| 318 | $rows[] = array( |
| 319 | 'name' => esc_html__( 'Matomo System Check', 'matomo' ), |
| 320 | 'value' => 'Failed to run, please open the system check in Matomo', |
| 321 | 'comment' => $e->getMessage(), |
| 322 | ); |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | $site = new Site(); |
| 327 | $idsite = $site->get_current_matomo_site_id(); |
| 328 | |
| 329 | $rows[] = array( |
| 330 | 'name' => esc_html__( 'Matomo Blog idSite', 'matomo' ), |
| 331 | 'value' => $idsite, |
| 332 | 'comment' => '', |
| 333 | ); |
| 334 | |
| 335 | $rows[] = array( |
| 336 | 'section' => 'Endpoints', |
| 337 | ); |
| 338 | |
| 339 | $rows[] = array( |
| 340 | 'name' => 'Matomo JavaScript Tracker URL', |
| 341 | 'value' => '', |
| 342 | 'comment' => $paths->get_js_tracker_url_in_matomo_dir(), |
| 343 | ); |
| 344 | |
| 345 | $rows[] = array( |
| 346 | 'name' => 'Matomo JavaScript Tracker - WP Rest API', |
| 347 | 'value' => '', |
| 348 | 'comment' => $paths->get_js_tracker_rest_api_endpoint(), |
| 349 | ); |
| 350 | |
| 351 | $rows[] = array( |
| 352 | 'name' => 'Matomo HTTP Tracking API', |
| 353 | 'value' => '', |
| 354 | 'comment' => $paths->get_tracker_api_url_in_matomo_dir(), |
| 355 | ); |
| 356 | |
| 357 | $rows[] = array( |
| 358 | 'name' => 'Matomo HTTP Tracking API - WP Rest API', |
| 359 | 'value' => '', |
| 360 | 'comment' => $paths->get_tracker_api_rest_api_endpoint(), |
| 361 | ); |
| 362 | |
| 363 | $matomo_plugin_dir_name = basename(dirname(MATOMO_ANALYTICS_FILE)); |
| 364 | if ($matomo_plugin_dir_name !== 'matomo') { |
| 365 | $rows[] = array( |
| 366 | 'name' => 'Matomo Plugin Name is correct', |
| 367 | 'value' => false, |
| 368 | 'is_error' => true, |
| 369 | 'comment' => 'The plugin name should be "matomo" but seems to be "' . $matomo_plugin_dir_name . '". As a result, admin pages and other features might not work. You might need to rename the directory name of this plugin and reactive the plugin.', |
| 370 | ); |
| 371 | } elseif (!is_plugin_active('matomo/matomo.php')) { |
| 372 | $rows[] = array( |
| 373 | 'name' => 'Matomo Plugin not active', |
| 374 | 'value' => false, |
| 375 | 'is_error' => true, |
| 376 | 'comment' => 'It seems WordPress thinks that `matomo/matomo.php` is not active. As a result Matomo reporting and admin pages may not work. You may be able to fix this by deactivating and activating the Matomo Analytics plugin. One of the reasons this could happen is that you used to have Matomo installed in the wrong folder.', |
| 377 | ); |
| 378 | } |
| 379 | |
| 380 | $rows[] = array( |
| 381 | 'section' => 'Crons', |
| 382 | ); |
| 383 | |
| 384 | $scheduled_tasks = new ScheduledTasks( $this->settings ); |
| 385 | $all_events = $scheduled_tasks->get_all_events(); |
| 386 | |
| 387 | $rows[] = array( |
| 388 | 'name' => esc_html__( 'Server time', 'matomo' ), |
| 389 | 'value' => $this->convert_time_to_date( time(), false ), |
| 390 | 'comment' => '', |
| 391 | ); |
| 392 | |
| 393 | $rows[] = array( |
| 394 | 'name' => esc_html__( 'Blog time', 'matomo' ), |
| 395 | 'value' => $this->convert_time_to_date( time(), true ), |
| 396 | 'comment' => esc_html__( 'Below dates are shown in blog timezone', 'matomo' ), |
| 397 | ); |
| 398 | |
| 399 | foreach ( $all_events as $event_name => $event_config ) { |
| 400 | $last_run_before = $scheduled_tasks->get_last_time_before_cron( $event_name ); |
| 401 | $last_run_after = $scheduled_tasks->get_last_time_after_cron( $event_name ); |
| 402 | |
| 403 | $next_scheduled = wp_next_scheduled( $event_name ); |
| 404 | |
| 405 | $comment = ' Last started: ' . $this->convert_time_to_date( $last_run_before, true, true ) . '.'; |
| 406 | $comment .= ' Last ended: ' . $this->convert_time_to_date( $last_run_after, true, true ) . '.'; |
| 407 | $comment .= ' Interval: ' . $event_config['interval']; |
| 408 | |
| 409 | $rows[] = array( |
| 410 | 'name' => $event_config['name'], |
| 411 | 'value' => 'Next run: ' . $this->convert_time_to_date( $next_scheduled, true, true ), |
| 412 | 'comment' => $comment, |
| 413 | ); |
| 414 | } |
| 415 | |
| 416 | if ( ! \WpMatomo::is_safe_mode() && $report ) { |
| 417 | $rows[] = array( |
| 418 | 'section' => esc_html__( 'Mandatory checks', 'matomo' ), |
| 419 | ); |
| 420 | |
| 421 | $rows = $this->add_diagnostic_results( $rows, $report->getMandatoryDiagnosticResults() ); |
| 422 | |
| 423 | $rows[] = array( |
| 424 | 'section' => esc_html__( 'Optional checks', 'matomo' ), |
| 425 | ); |
| 426 | $rows = $this->add_diagnostic_results( $rows, $report->getOptionalDiagnosticResults() ); |
| 427 | |
| 428 | $cli_multi = new CliMulti(); |
| 429 | |
| 430 | $rows[] = array( |
| 431 | 'name' => 'Supports Async Archiving', |
| 432 | 'value' => $cli_multi->supportsAsync(), |
| 433 | 'comment' => '', |
| 434 | ); |
| 435 | |
| 436 | $location_provider = LocationProvider::getCurrentProvider(); |
| 437 | if ($location_provider) { |
| 438 | $rows[] = array( |
| 439 | 'name' => 'Location provider ID', |
| 440 | 'value' => $location_provider->getId(), |
| 441 | 'comment' => '', |
| 442 | ); |
| 443 | $rows[] = array( |
| 444 | 'name' => 'Location provider available', |
| 445 | 'value' => $location_provider->isAvailable(), |
| 446 | 'comment' => '', |
| 447 | ); |
| 448 | $rows[] = array( |
| 449 | 'name' => 'Location provider working', |
| 450 | 'value' => $location_provider->isWorking(), |
| 451 | 'comment' => '', |
| 452 | ); |
| 453 | } |
| 454 | |
| 455 | $num_days_check_visits = 5; |
| 456 | $had_visits = $this->had_visits_in_last_days($num_days_check_visits); |
| 457 | if ($had_visits === false || $had_visits === true) { |
| 458 | // do not show info if we could not detect it (had_visits === null) |
| 459 | $comment = ''; |
| 460 | if (!$had_visits) { |
| 461 | $comment = 'It looks like there were no visits in the last ' . $num_days_check_visits . ' days. This may be expected if tracking is disabled, you have not added the tracking code, or your website does not have many visitors in general and you exclude your own visits.'; |
| 462 | } |
| 463 | |
| 464 | $rows[] = array( |
| 465 | 'name' => 'Had visit in last ' . $num_days_check_visits . ' days', |
| 466 | 'value' => $had_visits, |
| 467 | 'is_warning' => !$had_visits && $this->settings->is_tracking_enabled(), |
| 468 | 'comment' => $comment, |
| 469 | ); |
| 470 | } |
| 471 | |
| 472 | } |
| 473 | |
| 474 | $rows[] = array( |
| 475 | 'section' => 'Matomo Settings', |
| 476 | ); |
| 477 | |
| 478 | // always show these settings |
| 479 | $global_settings_always_show = array( |
| 480 | 'track_mode', |
| 481 | 'track_codeposition', |
| 482 | 'track_api_endpoint', |
| 483 | 'track_js_endpoint', |
| 484 | ); |
| 485 | foreach ( $global_settings_always_show as $key ) { |
| 486 | $rows[] = array( |
| 487 | 'name' => ucfirst( str_replace( '_', ' ', $key ) ), |
| 488 | 'value' => $this->settings->get_global_option( $key ), |
| 489 | 'comment' => '', |
| 490 | ); |
| 491 | } |
| 492 | |
| 493 | // otherwise show only few customised settings |
| 494 | // mostly only numeric values and booleans to not eg accidentally show anything that would store a token etc |
| 495 | // like we don't want to show license key etc |
| 496 | foreach ( $this->settings->get_customised_global_settings() as $key => $val ) { |
| 497 | if ( is_numeric( $val ) || is_bool( $val ) || 'track_content' === $key || 'track_user_id' === $key || 'core_version' === $key || 'version_history' === $key || 'mail_history' === $key ) { |
| 498 | if ( is_array( $val ) ) { |
| 499 | $val = implode( ', ', $val ); |
| 500 | } |
| 501 | |
| 502 | $rows[] = array( |
| 503 | 'name' => ucfirst( str_replace( '_', ' ', $key ) ), |
| 504 | 'value' => $val, |
| 505 | 'comment' => '', |
| 506 | ); |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | $rows[] = array( |
| 511 | 'section' => 'Logs', |
| 512 | ); |
| 513 | |
| 514 | $error_log_entries = $this->logger->get_last_logged_entries(); |
| 515 | if ( ! empty( $error_log_entries ) ) { |
| 516 | foreach ( $error_log_entries as $error ) { |
| 517 | $error['value'] = $this->convert_time_to_date( $error['value'], true, false ); |
| 518 | $error['is_warning'] = !empty($error['name']) && stripos($error['name'], 'archiv') !== false && $error['name'] !== 'archive_boot'; |
| 519 | $error['comment'] = matomo_anonymize_value($error['comment']); |
| 520 | $rows[] = $error; |
| 521 | } |
| 522 | } else { |
| 523 | $rows[] = array( |
| 524 | 'name' => __('None', 'matomo'), |
| 525 | 'value' => '', |
| 526 | 'comment' => '', |
| 527 | ); |
| 528 | } |
| 529 | |
| 530 | return $rows; |
| 531 | } |
| 532 | |
| 533 | private function had_visits_in_last_days($numDays) |
| 534 | { |
| 535 | global $wpdb; |
| 536 | |
| 537 | if (\WpMatomo::is_safe_mode()) { |
| 538 | return null; |
| 539 | } |
| 540 | |
| 541 | $days_in_seconds = $numDays * 86400; |
| 542 | $db = new \WpMatomo\Db\Settings(); |
| 543 | $prefix_table = $db->prefix_table_name('log_visit'); |
| 544 | |
| 545 | $suppress_errors = $wpdb->suppress_errors; |
| 546 | $wpdb->suppress_errors( true );// prevent any of this showing in logs just in case |
| 547 | |
| 548 | try { |
| 549 | $time = gmdate( 'Y-m-d H:i:s', time() - $days_in_seconds ); |
| 550 | $sql = $wpdb->prepare('SELECT count(idsite) from ' . $prefix_table . ' where visit_last_action_time > %s LIMIT 1', $time ); |
| 551 | $row = $wpdb->get_var( $sql ); |
| 552 | } catch ( \Exception $e ) { |
| 553 | $row = null; |
| 554 | } |
| 555 | |
| 556 | $wpdb->suppress_errors( $suppress_errors ); |
| 557 | // we need to differentiate between |
| 558 | // 0 === had no visit |
| 559 | // 1 === had visit |
| 560 | // null === sum error... eg table was not correctly installed |
| 561 | if ($row !== null) { |
| 562 | $row = !empty($row); |
| 563 | } |
| 564 | |
| 565 | return $row; |
| 566 | } |
| 567 | |
| 568 | private function convert_time_to_date( $time, $in_blog_timezone, $print_diff = false ) { |
| 569 | if ( empty( $time ) ) { |
| 570 | return esc_html__( 'Unknown', 'matomo' ); |
| 571 | } |
| 572 | |
| 573 | $date = gmdate( 'Y-m-d H:i:s', $time ); |
| 574 | |
| 575 | if ( $in_blog_timezone ) { |
| 576 | $date = get_date_from_gmt( $date, 'Y-m-d H:i:s' ); |
| 577 | } |
| 578 | |
| 579 | if ( $print_diff && class_exists( '\Piwik\MetricsFormatter' ) ) { |
| 580 | $date .= ' (' . MetricsFormatter::getPrettyTimeFromSeconds( $time - time(), true, false, true ) . ')'; |
| 581 | } |
| 582 | |
| 583 | return $date; |
| 584 | } |
| 585 | |
| 586 | private function add_diagnostic_results( $rows, $results ) { |
| 587 | foreach ( $results as $result ) { |
| 588 | $comment = ''; |
| 589 | /** @var DiagnosticResult $result */ |
| 590 | if ( $result->getStatus() !== DiagnosticResult::STATUS_OK ) { |
| 591 | foreach ( $result->getItems() as $item ) { |
| 592 | $item_comment = $item->getComment(); |
| 593 | if ( ! empty( $item_comment ) && is_string( $item_comment ) ) { |
| 594 | if ( stripos( $item_comment, 'core:archive' ) > 0 ) { |
| 595 | // we only want to keep the first sentence like " Archiving last ran successfully on Wednesday, January 2, 2019 00:00:00 which is 335 days 20:08:11 ago" |
| 596 | // but not anything that asks user to set up a cronjob |
| 597 | $item_comment = substr( $item_comment, 0, stripos( $item_comment, 'core:archive' ) ); |
| 598 | if ( strpos( $item_comment, '.' ) > 0 ) { |
| 599 | $item_comment = substr( $item_comment, 0, strripos( $item_comment, '.' ) ); |
| 600 | } else { |
| 601 | $item_comment = 'Archiving hasn\'t run in a while.'; |
| 602 | } |
| 603 | } |
| 604 | $comment .= $item_comment . '<br/>'; |
| 605 | } |
| 606 | } |
| 607 | } |
| 608 | |
| 609 | $rows[] = array( |
| 610 | 'name' => $result->getLabel(), |
| 611 | 'value' => $result->getStatus() . ' ' . $result->getLongErrorMessage(), |
| 612 | 'comment' => $comment, |
| 613 | 'is_warning' => $result->getStatus() === DiagnosticResult::STATUS_WARNING, |
| 614 | 'is_error' => $result->getStatus() === DiagnosticResult::STATUS_ERROR, |
| 615 | ); |
| 616 | } |
| 617 | |
| 618 | return $rows; |
| 619 | } |
| 620 | |
| 621 | private function get_wordpress_info() { |
| 622 | $is_multi_site = is_multisite(); |
| 623 | $num_blogs = 1; |
| 624 | $is_network_enabled = false; |
| 625 | if ( $is_multi_site ) { |
| 626 | if ( function_exists( 'get_blog_count' ) ) { |
| 627 | $num_blogs = get_blog_count(); |
| 628 | } |
| 629 | $settings = new Settings(); |
| 630 | $is_network_enabled = $settings->is_network_enabled(); |
| 631 | } |
| 632 | |
| 633 | $rows = array(); |
| 634 | $rows[] = array( |
| 635 | 'name' => 'Home URL', |
| 636 | 'value' => home_url(), |
| 637 | ); |
| 638 | $rows[] = array( |
| 639 | 'name' => 'Site URL', |
| 640 | 'value' => site_url(), |
| 641 | ); |
| 642 | $rows[] = array( |
| 643 | 'name' => 'WordPress Version', |
| 644 | 'value' => get_bloginfo( 'version' ), |
| 645 | ); |
| 646 | $rows[] = array( |
| 647 | 'name' => 'Number of blogs', |
| 648 | 'value' => $num_blogs, |
| 649 | ); |
| 650 | $rows[] = array( |
| 651 | 'name' => 'Multisite Enabled', |
| 652 | 'value' => $is_multi_site, |
| 653 | ); |
| 654 | $rows[] = array( |
| 655 | 'name' => 'Network Enabled', |
| 656 | 'value' => $is_network_enabled, |
| 657 | ); |
| 658 | $rows[] = array( |
| 659 | 'name' => 'Debug Mode Enabled', |
| 660 | 'value' => defined( 'WP_DEBUG' ) && WP_DEBUG, |
| 661 | ); |
| 662 | $rows[] = array( |
| 663 | 'name' => 'Cron Enabled', |
| 664 | 'value' => defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON, |
| 665 | ); |
| 666 | $rows[] = array( |
| 667 | 'name' => 'Force SSL Admin', |
| 668 | 'value' => defined( 'FORCE_SSL_ADMIN' ) && FORCE_SSL_ADMIN, |
| 669 | ); |
| 670 | |
| 671 | $rows[] = array( |
| 672 | 'name' => 'Language', |
| 673 | 'value' => defined( 'WPLANG' ) && WPLANG ? WPLANG : 'en_US', |
| 674 | ); |
| 675 | |
| 676 | $rows[] = array( |
| 677 | 'name' => 'Permalink Structure', |
| 678 | 'value' => get_option( 'permalink_structure' ) ? get_option( 'permalink_structure' ) : 'Default', |
| 679 | ); |
| 680 | |
| 681 | $rows[] = array( |
| 682 | 'name' => 'Possibly uses symlink', |
| 683 | 'value' => strpos( __DIR__, ABSPATH ) === false && strpos( __DIR__, WP_CONTENT_DIR ) === false, |
| 684 | ); |
| 685 | |
| 686 | $rows[] = array( |
| 687 | 'name' => 'WP Cache enabled', |
| 688 | 'value' => defined( 'WP_CACHE' ) && WP_CACHE, |
| 689 | ); |
| 690 | |
| 691 | if (is_plugin_active('wp-piwik/wp-piwik.php')) { |
| 692 | $rows[] = array( |
| 693 | 'name' => 'WP-Matomo (WP-Piwik) activated', |
| 694 | 'value' => true, |
| 695 | 'is_warning' => true, |
| 696 | 'comment' => 'It is usually not recommended or needed to run Matomo for WordPress and WP-Matomo at the same time. To learn more about the differences between the two plugins view this URL: https://matomo.org/faq/wordpress/why-are-there-two-different-matomo-for-wordpress-plugins-what-is-the-difference-to-wp-matomo-integration-plugin/' |
| 697 | ); |
| 698 | |
| 699 | $mode = get_option ( 'wp-piwik_global-piwik_mode' ); |
| 700 | if (function_exists('get_site_option') && is_plugin_active_for_network ( 'wp-piwik/wp-piwik.php' )) { |
| 701 | $mode = get_site_option ( 'wp-piwik_global-piwik_mode'); |
| 702 | } |
| 703 | if (!empty($mode)) { |
| 704 | $rows[] = array( |
| 705 | 'name' => 'WP-Matomo mode', |
| 706 | 'value' => $mode, |
| 707 | 'is_warning' => $mode === 'php' || $mode === 'PHP', |
| 708 | 'comment' => 'WP-Matomo is configured in "PHP mode". This is known to cause issues with Matomo for WordPress. We recommend you either deactivate WP-Matomo or you go "Settings => WP-Matomo" and change the "Matomo Mode" in the "Connect to Matomo" section to "Self-hosted HTTP API".' |
| 709 | ); |
| 710 | } |
| 711 | } |
| 712 | |
| 713 | $compatible_content_dir = matomo_has_compatible_content_dir(); |
| 714 | if ($compatible_content_dir === true) { |
| 715 | $rows[] = array( |
| 716 | 'name' => 'Compatible content directory', |
| 717 | 'value' => true, |
| 718 | ); |
| 719 | } else { |
| 720 | $rows[] = array( |
| 721 | 'name' => 'Compatible content directory', |
| 722 | 'value' => $compatible_content_dir, |
| 723 | 'is_warning' => true, |
| 724 | 'comment' => __( 'It looks like you are maybe using a custom WordPress content directory. The Matomo reporting/admin pages might not work. You may be able to workaround this.', 'matomo' ) . ' ' . __( 'Learn more', 'matomo' ) . ': https://matomo.org/faq/wordpress/how-do-i-make-matomo-for-wordpress-work-when-i-have-a-custom-content-directory/' |
| 725 | ); |
| 726 | } |
| 727 | |
| 728 | return $rows; |
| 729 | } |
| 730 | |
| 731 | private function get_server_info() { |
| 732 | $rows = array(); |
| 733 | |
| 734 | if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) { |
| 735 | $rows[] = array( |
| 736 | 'name' => 'Server Info', |
| 737 | 'value' => $_SERVER['SERVER_SOFTWARE'], |
| 738 | ); |
| 739 | } |
| 740 | if ( PHP_OS ) { |
| 741 | $rows[] = array( |
| 742 | 'name' => 'PHP OS', |
| 743 | 'value' => PHP_OS, |
| 744 | ); |
| 745 | } |
| 746 | $rows[] = array( |
| 747 | 'name' => 'PHP Version', |
| 748 | 'value' => phpversion(), |
| 749 | ); |
| 750 | $rows[] = array( |
| 751 | 'name' => 'PHP SAPI', |
| 752 | 'value' => php_sapi_name(), |
| 753 | ); |
| 754 | if (defined('PHP_BINARY') && PHP_BINARY) { |
| 755 | $rows[] = array( |
| 756 | 'name' => 'PHP Binary Name', |
| 757 | 'value' => @basename(PHP_BINARY), |
| 758 | ); |
| 759 | } |
| 760 | $rows[] = array( |
| 761 | 'name' => 'Timezone', |
| 762 | 'value' => date_default_timezone_get(), |
| 763 | ); |
| 764 | $rows[] = array( |
| 765 | 'name' => 'Locale', |
| 766 | 'value' => get_locale(), |
| 767 | ); |
| 768 | |
| 769 | $rows[] = array( |
| 770 | 'name' => 'Memory Limit', |
| 771 | 'value' => @ini_get( 'memory_limit' ), |
| 772 | 'comment' => 'At least 128MB recommended. Depending on your traffic 256MB or more may be needed.', |
| 773 | ); |
| 774 | |
| 775 | $rows[] = array( |
| 776 | 'name' => 'Max Memory Limit', |
| 777 | 'value' => defined( 'WP_MAX_MEMORY_LIMIT' ) ? WP_MAX_MEMORY_LIMIT : '', |
| 778 | 'comment' => '', |
| 779 | ); |
| 780 | |
| 781 | $rows[] = array( |
| 782 | 'name' => 'Time', |
| 783 | 'value' => time(), |
| 784 | ); |
| 785 | |
| 786 | $rows[] = array( |
| 787 | 'name' => 'Max Execution Time', |
| 788 | 'value' => ini_get( 'max_execution_time' ), |
| 789 | ); |
| 790 | $rows[] = array( |
| 791 | 'name' => 'Max Post Size', |
| 792 | 'value' => ini_get( 'post_max_size' ), |
| 793 | ); |
| 794 | $rows[] = array( |
| 795 | 'name' => 'Max Upload Size', |
| 796 | 'value' => wp_max_upload_size(), |
| 797 | ); |
| 798 | $rows[] = array( |
| 799 | 'name' => 'Max Input Vars', |
| 800 | 'value' => ini_get( 'max_input_vars' ), |
| 801 | ); |
| 802 | |
| 803 | $disabled_functions = ini_get('disable_functions'); |
| 804 | $rows[] = array( |
| 805 | 'name' => 'Disabled PHP functions', |
| 806 | 'value' => !empty($disabled_functions), |
| 807 | 'comment' => !empty($disabled_functions) ? $disabled_functions : '' |
| 808 | ); |
| 809 | |
| 810 | $zlib_compression = ini_get( 'zlib.output_compression' ); |
| 811 | $row = array( |
| 812 | 'name' => 'zlib.output_compression is off', |
| 813 | 'value' => $zlib_compression !== '1', |
| 814 | ); |
| 815 | |
| 816 | if ( $zlib_compression === '1' ) { |
| 817 | $row['is_error'] = true; |
| 818 | $row['comment'] = 'You need to set "zlib.output_compression" in your php.ini to "Off".'; |
| 819 | } |
| 820 | $rows[] = $row; |
| 821 | |
| 822 | if ( function_exists( 'curl_version' ) ) { |
| 823 | $curl_version = curl_version(); |
| 824 | $curl_version = $curl_version['version'] . ', ' . $curl_version['ssl_version']; |
| 825 | $rows[] = array( |
| 826 | 'name' => 'Curl Version', |
| 827 | 'value' => $curl_version, |
| 828 | ); |
| 829 | } |
| 830 | |
| 831 | return $rows; |
| 832 | } |
| 833 | |
| 834 | private function get_browser_info() { |
| 835 | $rows = array(); |
| 836 | |
| 837 | if (!empty($_SERVER['HTTP_USER_AGENT'])) { |
| 838 | $rows[] = array( |
| 839 | 'name' => 'Browser', |
| 840 | 'value' => $_SERVER['HTTP_USER_AGENT'], |
| 841 | ); |
| 842 | } |
| 843 | if (!\WpMatomo::is_safe_mode()) { |
| 844 | Bootstrap::do_bootstrap(); |
| 845 | $rows[] = array( |
| 846 | 'name' => 'Language', |
| 847 | 'value' => Common::getBrowserLanguage() |
| 848 | ); |
| 849 | } |
| 850 | |
| 851 | |
| 852 | return $rows; |
| 853 | } |
| 854 | |
| 855 | private function get_db_info() { |
| 856 | global $wpdb; |
| 857 | $rows = array(); |
| 858 | |
| 859 | $rows[] = array( |
| 860 | 'name' => 'MySQL Version', |
| 861 | 'value' => ! empty( $wpdb->is_mysql ) ? $wpdb->db_version() : '', |
| 862 | 'comment' => '', |
| 863 | ); |
| 864 | |
| 865 | $rows[] = array( |
| 866 | 'name' => 'Mysqli Connect', |
| 867 | 'value' => function_exists( 'mysqli_connect' ), |
| 868 | 'comment' => '', |
| 869 | ); |
| 870 | $rows[] = array( |
| 871 | 'name' => 'Force MySQL over Mysqli', |
| 872 | 'value' => defined( 'WP_USE_EXT_MYSQL' ) && WP_USE_EXT_MYSQL, |
| 873 | 'comment' => '', |
| 874 | ); |
| 875 | |
| 876 | $rows[] = array( |
| 877 | 'name' => 'DB Prefix', |
| 878 | 'value' => $wpdb->prefix, |
| 879 | ); |
| 880 | |
| 881 | if ( method_exists( $wpdb, 'parse_db_host' ) ) { |
| 882 | $host_data = $wpdb->parse_db_host( DB_HOST ); |
| 883 | if ( $host_data ) { |
| 884 | list( $host, $port, $socket, $is_ipv6 ) = $host_data; |
| 885 | } |
| 886 | |
| 887 | $rows[] = array( |
| 888 | 'name' => 'Uses Socket', |
| 889 | 'value' => ! empty( $socket ), |
| 890 | ); |
| 891 | $rows[] = array( |
| 892 | 'name' => 'Uses IPv6', |
| 893 | 'value' => ! empty( $is_ipv6 ), |
| 894 | ); |
| 895 | } |
| 896 | |
| 897 | $grants = $this->get_db_grants(); |
| 898 | |
| 899 | // we only show these grants for security reasons as only they are needed and we don't need to know any other ones |
| 900 | $needed_grants = array( 'SELECT', 'INSERT', 'UPDATE', 'INDEX', 'DELETE', 'CREATE', 'DROP', 'ALTER', 'CREATE TEMPORARY TABLES', 'LOCK TABLES' ); |
| 901 | if ( in_array( 'ALL PRIVILEGES', $grants, true ) ) { |
| 902 | // ALL PRIVILEGES may be used pre MySQL 8.0 |
| 903 | $grants = $needed_grants; |
| 904 | } |
| 905 | |
| 906 | $grants_missing = array_diff( $needed_grants, $grants ); |
| 907 | |
| 908 | if ( empty( $grants ) |
| 909 | || ! is_array( $grants ) |
| 910 | || count( $grants_missing ) === count( $needed_grants ) ) { |
| 911 | $rows[] = array( |
| 912 | 'name' => esc_html__( 'Required permissions', 'matomo' ), |
| 913 | 'value' => esc_html__( 'Failed to detect granted permissions', 'matomo' ), |
| 914 | 'comment' => esc_html__( 'Please check your MySQL user has these permissions (grants):', 'matomo' ) . '<br />' . implode( ', ', $needed_grants ), |
| 915 | 'is_warning' => false, |
| 916 | ); |
| 917 | } else { |
| 918 | if ( ! empty( $grants_missing ) ) { |
| 919 | $rows[] = array( |
| 920 | 'name' => esc_html__( 'Required permissions', 'matomo' ), |
| 921 | 'value' => esc_html__( 'Error', 'matomo' ), |
| 922 | 'comment' => esc_html__( 'Missing permissions', 'matomo' ) . ': ' . implode( ', ', $grants_missing ) . '. ' . __( 'Please check if any of these MySQL permission (grants) are missing and add them if needed.', 'matomo' ) . ' ' . __( 'Learn more', 'matomo' ) . ': https://matomo.org/faq/troubleshooting/how-do-i-check-if-my-mysql-user-has-all-required-grants/', |
| 923 | 'is_warning' => true, |
| 924 | ); |
| 925 | } else { |
| 926 | $rows[] = array( |
| 927 | 'name' => esc_html__( 'Required permissions', 'matomo' ), |
| 928 | 'value' => esc_html__( 'OK', 'matomo' ), |
| 929 | 'comment' => '', |
| 930 | 'is_warning' => false, |
| 931 | ); |
| 932 | } |
| 933 | } |
| 934 | |
| 935 | return $rows; |
| 936 | } |
| 937 | |
| 938 | private function get_db_grants() { |
| 939 | global $wpdb; |
| 940 | |
| 941 | $suppress_errors = $wpdb->suppress_errors; |
| 942 | $wpdb->suppress_errors( true );// prevent any of this showing in logs just in case |
| 943 | |
| 944 | try { |
| 945 | $values = $wpdb->get_results( 'SHOW GRANTS', ARRAY_N ); |
| 946 | } catch ( \Exception $e ) { |
| 947 | // We ignore any possible error in case of permission or not supported etc. |
| 948 | $values = array(); |
| 949 | } |
| 950 | |
| 951 | $wpdb->suppress_errors( $suppress_errors ); |
| 952 | |
| 953 | $grants = array(); |
| 954 | foreach ( $values as $index => $value ) { |
| 955 | if ( empty( $value[0] ) || ! is_string( $value[0] ) ) { |
| 956 | continue; |
| 957 | } |
| 958 | |
| 959 | if ( stripos( $value[0], 'ALL PRIVILEGES' ) !== false ) { |
| 960 | return array( 'ALL PRIVILEGES' ); // the split on empty string wouldn't work otherwise |
| 961 | } |
| 962 | |
| 963 | foreach ( array( ' ON ', ' TO ', ' IDENTIFIED ', ' BY ' ) as $keyword ) { |
| 964 | if ( stripos( $values[ $index ][0], $keyword ) !== false ) { |
| 965 | // make sure to never show by any accident a db user or password by cutting anything after on/to |
| 966 | $values[ $index ][0] = substr( $value[0], 0, stripos( $value[0], $keyword ) ); |
| 967 | } |
| 968 | if ( stripos( $values[ $index ][0], 'GRANT' ) !== false ) { |
| 969 | // otherwise we end up having "grant select"... instead of just "select" |
| 970 | $values[ $index ][0] = substr( $value[0], stripos( $values[ $index ][0], 'GRANT' ) + 5 ); |
| 971 | } |
| 972 | } |
| 973 | // make sure to never show by any accident a db user or password |
| 974 | $values[ $index ][0] = str_replace( array( DB_USER, DB_PASSWORD ), array( 'DB_USER', 'DB_PASS' ), $values[ $index ][0] ); |
| 975 | |
| 976 | $grants = array_merge( $grants, explode( ',', $values[ $index ][0] ) ); |
| 977 | } |
| 978 | $grants = array_map( 'trim', $grants ); |
| 979 | $grants = array_map( 'strtoupper', $grants ); |
| 980 | $grants = array_unique( $grants ); |
| 981 | return $grants; |
| 982 | } |
| 983 | |
| 984 | private function get_plugins_info() { |
| 985 | $rows = array(); |
| 986 | $mu_plugins = get_mu_plugins(); |
| 987 | |
| 988 | if ( ! empty( $mu_plugins ) ) { |
| 989 | $rows[] = array( |
| 990 | 'section' => 'MU Plugins', |
| 991 | ); |
| 992 | |
| 993 | foreach ( $mu_plugins as $mu_pin ) { |
| 994 | $comment = ''; |
| 995 | if ( ! empty( $plugin['Network'] ) ) { |
| 996 | $comment = 'Network enabled'; |
| 997 | } |
| 998 | $rows[] = array( |
| 999 | 'name' => $mu_pin['Name'], |
| 1000 | 'value' => $mu_pin['Version'], |
| 1001 | 'comment' => $comment, |
| 1002 | ); |
| 1003 | } |
| 1004 | |
| 1005 | $rows[] = array( |
| 1006 | 'section' => 'Plugins', |
| 1007 | ); |
| 1008 | } |
| 1009 | |
| 1010 | $plugins = get_plugins(); |
| 1011 | |
| 1012 | foreach ( $plugins as $plugin ) { |
| 1013 | $comment = ''; |
| 1014 | if ( ! empty( $plugin['Network'] ) ) { |
| 1015 | $comment = 'Network enabled'; |
| 1016 | } |
| 1017 | $rows[] = array( |
| 1018 | 'name' => $plugin['Name'], |
| 1019 | 'value' => $plugin['Version'], |
| 1020 | 'comment' => $comment, |
| 1021 | ); |
| 1022 | } |
| 1023 | |
| 1024 | $active_plugins = get_option( 'active_plugins', array() ); |
| 1025 | |
| 1026 | if ( ! empty( $active_plugins ) && is_array( $active_plugins ) ) { |
| 1027 | $active_plugins = array_map( |
| 1028 | function ( $active_plugin ) { |
| 1029 | $parts = explode( '/', trim( $active_plugin ) ); |
| 1030 | return trim( $parts[0] ); |
| 1031 | }, |
| 1032 | $active_plugins |
| 1033 | ); |
| 1034 | |
| 1035 | $rows[] = array( |
| 1036 | 'name' => 'Active Plugins', |
| 1037 | 'value' => count( $active_plugins ), |
| 1038 | 'comment' => implode( ' ', $active_plugins ), |
| 1039 | ); |
| 1040 | |
| 1041 | $used_not_compatible = array_intersect( $active_plugins, $this->not_compatible_plugins ); |
| 1042 | if ( ! empty( $used_not_compatible ) ) { |
| 1043 | $rows[] = array( |
| 1044 | 'name' => __( 'Not compatible plugins', 'matomo' ), |
| 1045 | 'value' => count( $used_not_compatible ), |
| 1046 | 'comment' => implode( ', ', $used_not_compatible ), |
| 1047 | 'is_error' => true, |
| 1048 | ); |
| 1049 | } |
| 1050 | } |
| 1051 | |
| 1052 | return $rows; |
| 1053 | } |
| 1054 | |
| 1055 | |
| 1056 | } |
| 1057 |