| @@ -136,52 +136,79 @@ | ||
| 136 | 136 | $rate_limit_log = get_option( 'metasync_otto_rate_limit_log', [] ); |
| 137 | 137 | $last_backoff_time = ! empty( $rate_limit_log ) ? max( $rate_limit_log ) : null; |
| 138 | 138 | $last_backoff_value = $last_backoff_time |
| 139 | 139 | ? wp_date( 'Y-m-d H:i:s', $last_backoff_time ) . ' (' . human_time_diff( $last_backoff_time ) . ' ago)' |
| 140 | - : __( 'Never' ); | |
| 140 | + : __( 'Never', 'metasync' ); | |
| 141 | 141 | |
| 142 | + $otto_job_counts = class_exists( 'Metasync_Otto_Job_Status' ) ? Metasync_Otto_Job_Status::counts() : []; | |
| 143 | + $otto_job_fields = []; | |
| 144 | + if ( ! empty( $otto_job_counts ) ) { | |
| 145 | + $otto_job_fields = [ | |
| 146 | + 'otto_jobs_accepted' => [ | |
| 147 | + 'label' => __( 'Crawl Jobs - Accepted', 'metasync' ), | |
| 148 | + 'value' => (int) $otto_job_counts['accepted'], | |
| 149 | + ], | |
| 150 | + 'otto_jobs_retrying' => [ | |
| 151 | + 'label' => __( 'Crawl Jobs - Retrying', 'metasync' ), | |
| 152 | + 'value' => (int) $otto_job_counts['retrying'], | |
| 153 | + ], | |
| 154 | + 'otto_jobs_completed' => [ | |
| 155 | + 'label' => __( 'Crawl Jobs - Completed', 'metasync' ), | |
| 156 | + 'value' => (int) $otto_job_counts['completed'], | |
| 157 | + ], | |
| 158 | + 'otto_jobs_failed' => [ | |
| 159 | + 'label' => __( 'Crawl Jobs - Failed', 'metasync' ), | |
| 160 | + 'value' => (int) $otto_job_counts['failed'], | |
| 161 | + ], | |
| 162 | + 'otto_jobs_pending' => [ | |
| 163 | + 'label' => __( 'Crawl Jobs - Queued Overflow', 'metasync' ), | |
| 164 | + 'value' => (int) $otto_job_counts['pending'], | |
| 165 | + ], | |
| 166 | + ]; | |
| 167 | + } | |
| 168 | + | |
| 142 | 169 | $info['metasync'] = [ |
| 143 | 170 | 'label' => $plugin_name, |
| 144 | 171 | 'fields' => [ |
| 145 | 172 | 'version' => [ |
| 146 | - 'label' => __( 'Plugin Version' ), | |
| 173 | + 'label' => __( 'Plugin Version', 'metasync' ), | |
| 147 | 174 | 'value' => METASYNC_VERSION, |
| 148 | 175 | ], |
| 149 | 176 | 'queue_pending' => [ |
| 150 | - 'label' => __( 'Queue - Pending Jobs' ), | |
| 177 | + 'label' => __( 'Queue - Pending Jobs', 'metasync' ), | |
| 151 | 178 | 'value' => isset( $queue_stats['metasync_pending'] ) ? (int) $queue_stats['metasync_pending'] : 0, |
| 152 | 179 | ], |
| 153 | 180 | 'queue_completed' => [ |
| 154 | - 'label' => __( 'Queue - Completed Jobs' ), | |
| 181 | + 'label' => __( 'Queue - Completed Jobs', 'metasync' ), | |
| 155 | 182 | 'value' => $completed_count, |
| 156 | 183 | ], |
| 157 | 184 | 'queue_failed_24h' => [ |
| 158 | - 'label' => __( 'Queue - Failed Jobs (last 24h)' ), | |
| 185 | + 'label' => __( 'Queue - Failed Jobs (last 24h)', 'metasync' ), | |
| 159 | 186 | 'value' => isset( $failed_stats['count'] ) ? (int) $failed_stats['count'] : 0, |
| 160 | 187 | ], |
| 161 | - ] + $performance_fields + [ | |
| 188 | + ] + $performance_fields + $otto_job_fields + [ | |
| 162 | 189 | 'last_api_backoff' => [ |
| 163 | - 'label' => __( 'Last API Backoff Event' ), | |
| 190 | + 'label' => __( 'Last API Backoff Event', 'metasync' ), | |
| 164 | 191 | 'value' => $last_backoff_value, |
| 165 | 192 | ], |
| 166 | 193 | 'memory_limit' => [ |
| 167 | - 'label' => __( 'Memory - PHP Limit' ), | |
| 194 | + 'label' => __( 'Memory - PHP Limit', 'metasync' ), | |
| 168 | 195 | 'value' => $memory_stats['limit_formatted'], |
| 169 | 196 | ], |
| 170 | 197 | 'memory_current' => [ |
| 171 | - 'label' => __( 'Memory - Current Usage' ), | |
| 198 | + 'label' => __( 'Memory - Current Usage', 'metasync' ), | |
| 172 | 199 | 'value' => $memory_stats['current_formatted'], |
| 173 | 200 | ], |
| 174 | 201 | 'memory_peak' => [ |
| 175 | - 'label' => __( 'Memory - Peak Usage' ), | |
| 202 | + 'label' => __( 'Memory - Peak Usage', 'metasync' ), | |
| 176 | 203 | 'value' => $memory_stats['peak_formatted'], |
| 177 | 204 | ], |
| 178 | 205 | 'memory_percentage' => [ |
| 179 | - 'label' => __( 'Memory - Usage Percentage' ), | |
| 180 | - 'value' => $unlimited ? __( 'N/A (unlimited)' ) : $memory_stats['percentage'] . '%', | |
| 206 | + 'label' => __( 'Memory - Usage Percentage', 'metasync' ), | |
| 207 | + 'value' => $unlimited ? __( 'N/A (unlimited)', 'metasync' ) : $memory_stats['percentage'] . '%', | |
| 181 | 208 | ], |
| 182 | 209 | 'memory_available' => [ |
| 183 | - 'label' => __( 'Memory - Available' ), | |
| 210 | + 'label' => __( 'Memory - Available', 'metasync' ), | |
| 184 | 211 | 'value' => $memory_stats['available_formatted'], |
| 185 | 212 | ], |
| 186 | 213 | ], |
| 187 | 214 | ]; |
| @@ -201,36 +228,45 @@ | ||
| 201 | 228 | { |
| 202 | 229 | add_filter('site_status_tests', function ($tests) { |
| 203 | 230 | // WordPress Cron Queue Health Check |
| 204 | 231 | $tests['direct']['metasync_queue_size'] = [ |
| 205 | - 'label' => __('WordPress Cron Queue Health'), | |
| 232 | + 'label' => __('WordPress Cron Queue Health', 'metasync'), | |
| 206 | 233 | 'test' => [$this, 'queue_size_check'] |
| 207 | 234 | ]; |
| 208 | 235 | |
| 209 | 236 | // Memory Usage Health Check |
| 210 | 237 | $tests['direct']['metasync_memory_usage'] = [ |
| 211 | - 'label' => __('PHP Memory Usage'), | |
| 238 | + 'label' => __('PHP Memory Usage', 'metasync'), | |
| 212 | 239 | 'test' => [$this, 'memory_usage_check'] |
| 213 | 240 | ]; |
| 214 | 241 | |
| 215 | 242 | // OTTO API Rate Limit Health Check |
| 216 | 243 | $tests['direct']['metasync_otto_rate_limit'] = [ |
| 217 | - 'label' => sprintf(__('%s OTTO API Rate Limit'), Metasync::get_effective_plugin_name()), | |
| 244 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 245 | + 'label' => sprintf(__('%s OTTO API Rate Limit', 'metasync'), Metasync::get_effective_plugin_name()), | |
| 218 | 246 | 'test' => [$this, 'otto_rate_limit_check'] |
| 219 | 247 | ]; |
| 220 | 248 | |
| 221 | 249 | // Debug Mode Health Check |
| 222 | 250 | $tests['direct']['metasync_debug_mode'] = [ |
| 223 | - 'label' => __('WordPress Debug Mode'), | |
| 251 | + 'label' => __('WordPress Debug Mode', 'metasync'), | |
| 224 | 252 | 'test' => [$this, 'debug_mode_check'] |
| 225 | 253 | ]; |
| 226 | 254 | |
| 227 | 255 | // Failed Actions Health Check |
| 228 | 256 | $tests['direct']['metasync_failed_actions'] = [ |
| 229 | - 'label' => sprintf(__('%s Failed Actions'), Metasync::get_effective_plugin_name()), | |
| 257 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 258 | + 'label' => sprintf(__('%s Failed Actions', 'metasync'), Metasync::get_effective_plugin_name()), | |
| 230 | 259 | 'test' => [$this, 'failed_actions_check'] |
| 231 | 260 | ]; |
| 232 | 261 | |
| 262 | + // OTTO Crawl Job Reliability Health Check | |
| 263 | + $tests['direct']['metasync_otto_job_reliability'] = [ | |
| 264 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 265 | + 'label' => sprintf(__('%s Crawl Job Reliability', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 266 | + 'test' => [$this, 'otto_job_reliability_check'] | |
| 267 | + ]; | |
| 268 | + | |
| 233 | 269 | return $tests; |
| 234 | 270 | }); |
| 235 | 271 | } |
| 236 | 272 | |
| @@ -247,9 +283,9 @@ | ||
| 247 | 283 | private function get_cron_option_size() |
| 248 | 284 | { |
| 249 | 285 | global $wpdb; |
| 250 | 286 | |
| 251 | - $size = $wpdb->get_var( | |
| 287 | + $size = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Site Health diagnostic — live on-demand size probe in wp-admin; caching would serve stale sizes | |
| 252 | 288 | $wpdb->prepare( |
| 253 | 289 | "SELECT LENGTH(option_value) FROM {$wpdb->options} WHERE option_name = %s", |
| 254 | 290 | 'cron' |
| 255 | 291 | ) |
| @@ -361,9 +397,9 @@ | ||
| 361 | 397 | |
| 362 | 398 | // Handle excessive size error |
| 363 | 399 | if (isset($stats['error']) && $stats['error'] === 'excessive_size') { |
| 364 | 400 | return [ |
| 365 | - 'label' => __('WordPress cron queue is excessively large'), | |
| 401 | + 'label' => __('WordPress cron queue is excessively large', 'metasync'), | |
| 366 | 402 | 'status' => 'critical', |
| 367 | 403 | 'badge' => [ |
| 368 | 404 | 'label' => Metasync::get_effective_plugin_name(), |
| 369 | 405 | 'color' => 'red' |
| @@ -368,10 +404,11 @@ | ||
| 368 | 404 | 'label' => Metasync::get_effective_plugin_name(), |
| 369 | 405 | 'color' => 'red' |
| 370 | 406 | ], |
| 371 | 407 | 'description' => sprintf( |
| 372 | - '<p>' . __('The WordPress cron data is excessively large (%s). This can cause severe performance issues including slow page loads, high memory usage, and potential timeouts.') . '</p>' . | |
| 373 | - '<p>' . __('This typically occurs when cron jobs accumulate from deactivated plugins or failed operations.') . '</p>', | |
| 408 | + /* translators: %s: formatted size of the cron data. */ | |
| 409 | + '<p>' . __('The WordPress cron data is excessively large (%s). This can cause severe performance issues including slow page loads, high memory usage, and potential timeouts.', 'metasync') . '</p>' . | |
| 410 | + '<p>' . __('This typically occurs when cron jobs accumulate from deactivated plugins or failed operations.', 'metasync') . '</p>', | |
| 374 | 411 | size_format($stats['size']) |
| 375 | 412 | ), |
| 376 | 413 | 'actions' => sprintf( |
| 377 | 414 | '<p><strong>%s</strong></p>' . |
| @@ -379,12 +416,12 @@ | ||
| 379 | 416 | '<li>%s</li>' . |
| 380 | 417 | '<li>%s</li>' . |
| 381 | 418 | '<li>%s</li>' . |
| 382 | 419 | '</ul>', |
| 383 | - __('Recommended Actions:'), | |
| 384 | - __('Use WP-CLI to list and clean up old cron jobs: <code>wp cron event list</code>'), | |
| 385 | - __('Install a cron management plugin to identify and remove orphaned jobs'), | |
| 386 | - __('Consider clearing the cron option and letting WordPress rebuild it from active plugins') | |
| 420 | + __('Recommended Actions:', 'metasync'), | |
| 421 | + __('Use WP-CLI to list and clean up old cron jobs: <code>wp cron event list</code>', 'metasync'), | |
| 422 | + __('Install a cron management plugin to identify and remove orphaned jobs', 'metasync'), | |
| 423 | + __('Consider clearing the cron option and letting WordPress rebuild it from active plugins', 'metasync') | |
| 387 | 424 | ), |
| 388 | 425 | 'test' => 'metasync_queue_size' |
| 389 | 426 | ]; |
| 390 | 427 | } |
| @@ -397,12 +434,12 @@ | ||
| 397 | 434 | // Determine status based on TOTAL system-wide ONE-TIME jobs from ALL sources |
| 398 | 435 | // This includes WordPress core, all plugins, themes, and custom code |
| 399 | 436 | if ($one_time_count <= self::PENDING_JOBS_THRESHOLD) { |
| 400 | 437 | $status = 'good'; |
| 401 | - $label = __('WordPress cron queue is healthy'); | |
| 438 | + $label = __('WordPress cron queue is healthy', 'metasync'); | |
| 402 | 439 | } else { |
| 403 | 440 | $status = 'critical'; |
| 404 | - $label = __('WordPress cron queue has high pending job count'); | |
| 441 | + $label = __('WordPress cron queue has high pending job count', 'metasync'); | |
| 405 | 442 | } |
| 406 | 443 | |
| 407 | 444 | // Build detailed description showing system-wide statistics |
| 408 | 445 | $description = sprintf( |
| @@ -411,14 +448,16 @@ | ||
| 411 | 448 | '<li>%s <strong>%s</strong></li>' . |
| 412 | 449 | '<li>%s %d</li>' . |
| 413 | 450 | '<li>%s %d</li>' . |
| 414 | 451 | '</ul>', |
| 415 | - __('WordPress Cron Queue Statistics (All Sources):'), | |
| 416 | - __('Total pending jobs (one-time events):'), | |
| 417 | - $truncated ? sprintf(__('%d+'), $one_time_count) : number_format($one_time_count), | |
| 418 | - __('Total scheduled events (recurring):'), | |
| 452 | + __('WordPress Cron Queue Statistics (All Sources):', 'metasync'), | |
| 453 | + __('Total pending jobs (one-time events):', 'metasync'), | |
| 454 | + /* translators: %d: number of pending one-time cron events. */ | |
| 455 | + $truncated ? sprintf(__('%d+', 'metasync'), $one_time_count) : number_format($one_time_count), | |
| 456 | + __('Total scheduled events (recurring):', 'metasync'), | |
| 419 | 457 | $recurring_count, |
| 420 | - sprintf(__('%s pending jobs:'), Metasync::get_effective_plugin_name()), | |
| 458 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 459 | + sprintf(__('%s pending jobs:', 'metasync'), Metasync::get_effective_plugin_name()), | |
| 421 | 460 | $metasync_count |
| 422 | 461 | ); |
| 423 | 462 | |
| 424 | 463 | // Add context about what these numbers mean |
| @@ -423,13 +462,17 @@ | ||
| 423 | 462 | |
| 424 | 463 | // Add context about what these numbers mean |
| 425 | 464 | $description .= sprintf( |
| 426 | 465 | '<p><em>%s</em></p>', |
| 427 | - __('Pending jobs are one-time tasks awaiting execution. Recurring events are permanent schedules that run automatically.') | |
| 466 | + __('Pending jobs are one-time tasks awaiting execution. Recurring events are permanent schedules that run automatically.', 'metasync') | |
| 428 | 467 | ); |
| 429 | 468 | |
| 430 | - // If status is not good, provide actionable recommendations | |
| 431 | - if ($status === 'recommended') { | |
| 469 | + // If status is not good, provide actionable recommendations. The | |
| 470 | + // status is only ever 'good' or 'critical' here, so the previous | |
| 471 | + // '=== recommended' comparison made this entire guidance block dead | |
| 472 | + // code — exactly when the queue went critical, operators got no | |
| 473 | + // diagnostics at all. | |
| 474 | + if ($status !== 'good') { | |
| 432 | 475 | $description .= sprintf( |
| 433 | 476 | '<p><strong>%s</strong></p>' . |
| 434 | 477 | '<ul>' . |
| 435 | 478 | '<li>%s</li>' . |
| @@ -435,12 +478,12 @@ | ||
| 435 | 478 | '<li>%s</li>' . |
| 436 | 479 | '<li>%s</li>' . |
| 437 | 480 | '<li>%s</li>' . |
| 438 | 481 | '</ul>', |
| 439 | - __('A high number of pending jobs may indicate:'), | |
| 440 | - __('WordPress cron is not running properly (check if WP-Cron is disabled or blocked)'), | |
| 441 | - __('High volume of scheduled tasks from plugins creating jobs faster than they can be processed'), | |
| 442 | - __('Slow server performance or resource constraints preventing timely job execution') | |
| 482 | + __('A high number of pending jobs may indicate:', 'metasync'), | |
| 483 | + __('WordPress cron is not running properly (check if WP-Cron is disabled or blocked)', 'metasync'), | |
| 484 | + __('High volume of scheduled tasks from plugins creating jobs faster than they can be processed', 'metasync'), | |
| 485 | + __('Slow server performance or resource constraints preventing timely job execution', 'metasync') | |
| 443 | 486 | ); |
| 444 | 487 | |
| 445 | 488 | // If MetaSync is a significant contributor, add specific guidance |
| 446 | 489 | if ($metasync_count > 500) { |
| @@ -445,11 +488,13 @@ | ||
| 445 | 488 | // If MetaSync is a significant contributor, add specific guidance |
| 446 | 489 | if ($metasync_count > 500) { |
| 447 | 490 | $description .= sprintf( |
| 448 | 491 | '<p><strong>%s</strong> %s</p>', |
| 449 | - sprintf(__('%s Contribution:'), Metasync::get_effective_plugin_name()), | |
| 492 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 493 | + sprintf(__('%s Contribution:', 'metasync'), Metasync::get_effective_plugin_name()), | |
| 450 | 494 | sprintf( |
| 451 | - __('%1$s has %2$s pending %3$s SEO processing jobs. This may indicate high crawl volume from %3$s or slow processing. Consider reviewing %3$s crawl settings if this number continues to grow.'), | |
| 495 | + /* translators: 1: effective plugin name (whitelabel-aware), 2: formatted job count, 3: OTTO name (whitelabel). */ | |
| 496 | + __('%1$s has %2$s pending %3$s SEO processing jobs. This may indicate high crawl volume from %3$s or slow processing. Consider reviewing %3$s crawl settings if this number continues to grow.', 'metasync'), | |
| 452 | 497 | Metasync::get_effective_plugin_name(), |
| 453 | 498 | number_format($metasync_count), |
| 454 | 499 | Metasync::get_whitelabel_otto_name() |
| 455 | 500 | ) |
| @@ -463,21 +508,21 @@ | ||
| 463 | 508 | '<li>%s</li>' . |
| 464 | 509 | '<li>%s</li>' . |
| 465 | 510 | '<li>%s</li>' . |
| 466 | 511 | '</ul>', |
| 467 | - __('Recommended Actions:'), | |
| 468 | - __('Verify WordPress cron is functioning: Tools → Site Health → Info → WordPress Constants → DISABLE_WP_CRON should be false'), | |
| 469 | - __('Check server logs for cron execution errors or timeouts'), | |
| 470 | - __('Consider using a real system cron instead of WP-Cron for better reliability') | |
| 512 | + __('Recommended Actions:', 'metasync'), | |
| 513 | + __('Verify WordPress cron is functioning: Tools → Site Health → Info → WordPress Constants → DISABLE_WP_CRON should be false', 'metasync'), | |
| 514 | + __('Check server logs for cron execution errors or timeouts', 'metasync'), | |
| 515 | + __('Consider using a real system cron instead of WP-Cron for better reliability', 'metasync') | |
| 471 | 516 | ); |
| 472 | 517 | |
| 473 | 518 | $description .= sprintf( |
| 474 | 519 | '<p>%s %s</p>', |
| 475 | - __( 'Quick link:' ), | |
| 520 | + __( 'Quick link:', 'metasync' ), | |
| 476 | 521 | sprintf( |
| 477 | 522 | '<a href="%s">%s</a>', |
| 478 | 523 | esc_url( admin_url( 'site-health.php?tab=debug' ) ), |
| 479 | - esc_html( __( 'Site Health Info (check DISABLE_WP_CRON)' ) ) | |
| 524 | + esc_html( __( 'Site Health Info (check DISABLE_WP_CRON)', 'metasync' ) ) | |
| 480 | 525 | ) |
| 481 | 526 | ); |
| 482 | 527 | } |
| 483 | 528 | |
| @@ -542,9 +587,9 @@ | ||
| 542 | 587 | if ($memory_limit === '-1') { |
| 543 | 588 | return [ |
| 544 | 589 | 'limit' => -1, |
| 545 | 590 | 'limit_bytes' => -1, |
| 546 | - 'limit_formatted' => __('Unlimited'), | |
| 591 | + 'limit_formatted' => __('Unlimited', 'metasync'), | |
| 547 | 592 | 'current' => memory_get_usage(true), |
| 548 | 593 | 'current_formatted' => size_format(memory_get_usage(true)), |
| 549 | 594 | 'peak' => memory_get_peak_usage(true), |
| 550 | 595 | 'peak_formatted' => size_format(memory_get_peak_usage(true)), |
| @@ -549,9 +594,9 @@ | ||
| 549 | 594 | 'peak' => memory_get_peak_usage(true), |
| 550 | 595 | 'peak_formatted' => size_format(memory_get_peak_usage(true)), |
| 551 | 596 | 'percentage' => 0, |
| 552 | 597 | 'available' => -1, |
| 553 | - 'available_formatted' => __('Unlimited') | |
| 598 | + 'available_formatted' => __('Unlimited', 'metasync') | |
| 554 | 599 | ]; |
| 555 | 600 | } |
| 556 | 601 | |
| 557 | 602 | // Convert limit to bytes |
| @@ -600,9 +645,9 @@ | ||
| 600 | 645 | |
| 601 | 646 | // Handle unlimited memory |
| 602 | 647 | if ($stats['limit_bytes'] === -1) { |
| 603 | 648 | return [ |
| 604 | - 'label' => __('PHP memory limit is unlimited'), | |
| 649 | + 'label' => __('PHP memory limit is unlimited', 'metasync'), | |
| 605 | 650 | 'status' => 'good', |
| 606 | 651 | 'badge' => [ |
| 607 | 652 | 'label' => Metasync::get_effective_plugin_name(), |
| 608 | 653 | 'color' => 'green' |
| @@ -613,13 +658,13 @@ | ||
| 613 | 658 | '<ul>' . |
| 614 | 659 | '<li>%s %s</li>' . |
| 615 | 660 | '<li>%s %s</li>' . |
| 616 | 661 | '</ul>', |
| 617 | - __('PHP memory limit is set to unlimited. While this prevents memory errors, it may allow poorly optimized code to consume excessive server resources.'), | |
| 618 | - __('Current Memory Usage:'), | |
| 619 | - __('Current usage:'), | |
| 662 | + __('PHP memory limit is set to unlimited. While this prevents memory errors, it may allow poorly optimized code to consume excessive server resources.', 'metasync'), | |
| 663 | + __('Current Memory Usage:', 'metasync'), | |
| 664 | + __('Current usage:', 'metasync'), | |
| 620 | 665 | $stats['current_formatted'], |
| 621 | - __('Peak usage:'), | |
| 666 | + __('Peak usage:', 'metasync'), | |
| 622 | 667 | $stats['peak_formatted'] |
| 623 | 668 | ), |
| 624 | 669 | 'test' => 'metasync_memory_usage' |
| 625 | 670 | ]; |
| @@ -629,12 +674,12 @@ | ||
| 629 | 674 | |
| 630 | 675 | // Determine status based on memory usage percentage |
| 631 | 676 | if ($percentage > self::MEMORY_CRITICAL_THRESHOLD) { |
| 632 | 677 | $status = 'critical'; |
| 633 | - $label = __('PHP memory usage is critically high'); | |
| 678 | + $label = __('PHP memory usage is critically high', 'metasync'); | |
| 634 | 679 | } else { |
| 635 | 680 | $status = 'good'; |
| 636 | - $label = __('PHP memory usage is healthy'); | |
| 681 | + $label = __('PHP memory usage is healthy', 'metasync'); | |
| 637 | 682 | } |
| 638 | 683 | |
| 639 | 684 | // Build detailed description |
| 640 | 685 | $description = sprintf( |
| @@ -645,19 +690,19 @@ | ||
| 645 | 690 | '<li>%s %s</li>' . |
| 646 | 691 | '<li>%s <strong>%.2f%%</strong></li>' . |
| 647 | 692 | '<li>%s %s</li>' . |
| 648 | 693 | '</ul>', |
| 649 | - __('PHP Memory Statistics:'), | |
| 650 | - __('Memory limit:'), | |
| 694 | + __('PHP Memory Statistics:', 'metasync'), | |
| 695 | + __('Memory limit:', 'metasync'), | |
| 651 | 696 | $stats['limit_formatted'], |
| 652 | 697 | $stats['limit'], |
| 653 | - __('Current usage:'), | |
| 698 | + __('Current usage:', 'metasync'), | |
| 654 | 699 | $stats['current_formatted'], |
| 655 | - __('Peak usage:'), | |
| 700 | + __('Peak usage:', 'metasync'), | |
| 656 | 701 | $stats['peak_formatted'], |
| 657 | - __('Usage percentage:'), | |
| 702 | + __('Usage percentage:', 'metasync'), | |
| 658 | 703 | $percentage, |
| 659 | - __('Available memory:'), | |
| 704 | + __('Available memory:', 'metasync'), | |
| 660 | 705 | $stats['available_formatted'] |
| 661 | 706 | ); |
| 662 | 707 | |
| 663 | 708 | // Add context about memory usage |
| @@ -663,9 +708,9 @@ | ||
| 663 | 708 | // Add context about memory usage |
| 664 | 709 | if ($status === 'good') { |
| 665 | 710 | $description .= sprintf( |
| 666 | 711 | '<p><em>%s</em></p>', |
| 667 | - __('Memory usage is within acceptable limits. The site has sufficient memory available for normal operations.') | |
| 712 | + __('Memory usage is within acceptable limits. The site has sufficient memory available for normal operations.', 'metasync') | |
| 668 | 713 | ); |
| 669 | 714 | } else { |
| 670 | 715 | // Critical status - provide actionable recommendations |
| 671 | 716 | $description .= sprintf( |
| @@ -676,14 +721,14 @@ | ||
| 676 | 721 | '<li>%s</li>' . |
| 677 | 722 | '<li>%s</li>' . |
| 678 | 723 | '<li>%s</li>' . |
| 679 | 724 | '</ul>', |
| 680 | - __('Critical Memory Usage Detected:'), | |
| 681 | - __('PHP memory usage is critically high (>90%). This may cause:'), | |
| 682 | - __('Fatal errors: "Allowed memory size exhausted"'), | |
| 683 | - __('Failed page loads and white screens'), | |
| 684 | - __('Incomplete plugin/theme operations'), | |
| 685 | - __('Performance degradation and slow response times') | |
| 725 | + __('Critical Memory Usage Detected:', 'metasync'), | |
| 726 | + __('PHP memory usage is critically high (>90%). This may cause:', 'metasync'), | |
| 727 | + __('Fatal errors: "Allowed memory size exhausted"', 'metasync'), | |
| 728 | + __('Failed page loads and white screens', 'metasync'), | |
| 729 | + __('Incomplete plugin/theme operations', 'metasync'), | |
| 730 | + __('Performance degradation and slow response times', 'metasync') | |
| 686 | 731 | ); |
| 687 | 732 | |
| 688 | 733 | $description .= sprintf( |
| 689 | 734 | '<p><strong>%s</strong></p>' . |
| @@ -693,17 +738,18 @@ | ||
| 693 | 738 | '<li>%s</li>' . |
| 694 | 739 | '<li>%s</li>' . |
| 695 | 740 | '<li>%s</li>' . |
| 696 | 741 | '</ul>', |
| 697 | - __('Recommended Actions:'), | |
| 742 | + __('Recommended Actions:', 'metasync'), | |
| 698 | 743 | sprintf( |
| 699 | - __('Increase PHP memory limit in wp-config.php: <code>define(\'WP_MEMORY_LIMIT\', \'256M\');</code> (current: %s)'), | |
| 744 | + /* translators: %s: current PHP memory limit. */ | |
| 745 | + __('Increase PHP memory limit in wp-config.php: <code>define(\'WP_MEMORY_LIMIT\', \'256M\');</code> (current: %s)', 'metasync'), | |
| 700 | 746 | $stats['limit'] |
| 701 | 747 | ), |
| 702 | - __('Contact your hosting provider to increase server memory limits'), | |
| 703 | - __('Deactivate unnecessary plugins that consume excessive memory'), | |
| 704 | - __('Optimize images and reduce media library size'), | |
| 705 | - __('Consider upgrading to a hosting plan with more resources') | |
| 748 | + __('Contact your hosting provider to increase server memory limits', 'metasync'), | |
| 749 | + __('Deactivate unnecessary plugins that consume excessive memory', 'metasync'), | |
| 750 | + __('Optimize images and reduce media library size', 'metasync'), | |
| 751 | + __('Consider upgrading to a hosting plan with more resources', 'metasync') | |
| 706 | 752 | ); |
| 707 | 753 | |
| 708 | 754 | // Add warning if peak usage is also high |
| 709 | 755 | if ($stats['peak'] > ($stats['limit_bytes'] * 0.95)) { |
| @@ -708,11 +754,12 @@ | ||
| 708 | 754 | // Add warning if peak usage is also high |
| 709 | 755 | if ($stats['peak'] > ($stats['limit_bytes'] * 0.95)) { |
| 710 | 756 | $description .= sprintf( |
| 711 | 757 | '<p><strong>%s</strong> %s</p>', |
| 712 | - __('Warning:'), | |
| 758 | + __('Warning:', 'metasync'), | |
| 713 | 759 | sprintf( |
| 714 | - __('Peak memory usage (%s) is very close to the limit. Memory errors may occur during high-traffic periods or resource-intensive operations.'), | |
| 760 | + /* translators: %s: formatted peak memory usage. */ | |
| 761 | + __('Peak memory usage (%s) is very close to the limit. Memory errors may occur during high-traffic periods or resource-intensive operations.', 'metasync'), | |
| 715 | 762 | $stats['peak_formatted'] |
| 716 | 763 | ) |
| 717 | 764 | ); |
| 718 | 765 | } |
| @@ -718,13 +765,13 @@ | ||
| 718 | 765 | } |
| 719 | 766 | |
| 720 | 767 | $description .= sprintf( |
| 721 | 768 | '<p>%s %s</p>', |
| 722 | - __( 'Quick link:' ), | |
| 769 | + __( 'Quick link:', 'metasync' ), | |
| 723 | 770 | sprintf( |
| 724 | 771 | '<a href="%s">%s</a>', |
| 725 | 772 | esc_url( admin_url( 'plugins.php' ) ), |
| 726 | - esc_html( __( 'Manage Plugins (deactivate memory-heavy plugins)' ) ) | |
| 773 | + esc_html( __( 'Manage Plugins (deactivate memory-heavy plugins)', 'metasync' ) ) | |
| 727 | 774 | ) |
| 728 | 775 | ); |
| 729 | 776 | } |
| 730 | 777 | |
| @@ -785,17 +832,19 @@ | ||
| 785 | 832 | |
| 786 | 833 | // Format the last hit timestamp if available |
| 787 | 834 | $last_hit_text = $last_hit |
| 788 | 835 | ? sprintf( |
| 789 | - __('Last occurrence: %s'), | |
| 836 | + /* translators: %s: date and time of the last occurrence. */ | |
| 837 | + __('Last occurrence: %s', 'metasync'), | |
| 790 | 838 | date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $last_hit) |
| 791 | 839 | ) |
| 792 | - : __('No rate limit hits recorded.'); | |
| 840 | + : __('No rate limit hits recorded.', 'metasync'); | |
| 793 | 841 | |
| 794 | 842 | if ($hits >= self::RATE_LIMIT_CRITICAL_THRESHOLD) { |
| 795 | 843 | $status = 'critical'; |
| 796 | 844 | $label = sprintf( |
| 797 | - __('%s OTTO API is being rate limited frequently (%d times in 24h)'), | |
| 845 | + /* translators: 1: effective plugin name (whitelabel-aware), 2: number of rate limit hits. */ | |
| 846 | + __('%1$s OTTO API is being rate limited frequently (%2$d times in 24h)', 'metasync'), | |
| 798 | 847 | Metasync::get_effective_plugin_name(), |
| 799 | 848 | $hits |
| 800 | 849 | ); |
| 801 | 850 | } elseif ($hits >= self::RATE_LIMIT_WARNING_THRESHOLD) { |
| @@ -800,15 +849,17 @@ | ||
| 800 | 849 | ); |
| 801 | 850 | } elseif ($hits >= self::RATE_LIMIT_WARNING_THRESHOLD) { |
| 802 | 851 | $status = 'recommended'; |
| 803 | 852 | $label = sprintf( |
| 804 | - __('%s OTTO API rate limit hit %d times in the last 24 hours'), | |
| 853 | + /* translators: 1: effective plugin name (whitelabel-aware), 2: number of rate limit hits. */ | |
| 854 | + __('%1$s OTTO API rate limit hit %2$d times in the last 24 hours', 'metasync'), | |
| 805 | 855 | Metasync::get_effective_plugin_name(), |
| 806 | 856 | $hits |
| 807 | 857 | ); |
| 808 | 858 | } else { |
| 809 | 859 | $status = 'good'; |
| 810 | - $label = sprintf(__('%s OTTO API rate limits are within normal range'), Metasync::get_effective_plugin_name()); | |
| 860 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 861 | + $label = sprintf(__('%s OTTO API rate limits are within normal range', 'metasync'), Metasync::get_effective_plugin_name()); | |
| 811 | 862 | } |
| 812 | 863 | |
| 813 | 864 | // Build description |
| 814 | 865 | $description = sprintf( |
| @@ -816,10 +867,11 @@ | ||
| 816 | 867 | '<ul>' . |
| 817 | 868 | '<li>%s <strong>%d</strong></li>' . |
| 818 | 869 | '<li>%s</li>' . |
| 819 | 870 | '</ul>', |
| 820 | - sprintf(__('%s API Rate Limit Statistics (last 24 hours):'), Metasync::get_whitelabel_otto_name()), | |
| 821 | - __('HTTP 429 responses received:'), | |
| 871 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 872 | + sprintf(__('%s API Rate Limit Statistics (last 24 hours):', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 873 | + __('HTTP 429 responses received:', 'metasync'), | |
| 822 | 874 | $hits, |
| 823 | 875 | $last_hit_text |
| 824 | 876 | ); |
| 825 | 877 | |
| @@ -825,9 +877,10 @@ | ||
| 825 | 877 | |
| 826 | 878 | if ($status === 'good') { |
| 827 | 879 | $description .= sprintf( |
| 828 | 880 | '<p><em>%s</em></p>', |
| 829 | - sprintf(__('The %s API is responding normally. No action required.'), Metasync::get_whitelabel_otto_name()) | |
| 881 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 882 | + sprintf(__('The %s API is responding normally. No action required.', 'metasync'), Metasync::get_whitelabel_otto_name()) | |
| 830 | 883 | ); |
| 831 | 884 | } else { |
| 832 | 885 | $description .= sprintf( |
| 833 | 886 | '<p><strong>%s</strong></p>' . |
| @@ -836,19 +889,23 @@ | ||
| 836 | 889 | '<li>%s</li>' . |
| 837 | 890 | '<li>%s</li>' . |
| 838 | 891 | '<li>%s</li>' . |
| 839 | 892 | '</ul>', |
| 840 | - sprintf(__('Frequent rate limiting can degrade %s SEO data delivery on your site.'), Metasync::get_whitelabel_otto_name()), | |
| 841 | - __('Recommended Actions:'), | |
| 842 | - sprintf(__('Review your %1$s crawl frequency settings in the %2$s dashboard to reduce request volume.'), Metasync::get_whitelabel_otto_name(), Metasync::get_effective_plugin_name()), | |
| 843 | - sprintf(__('Check if multiple server processes are triggering %s jobs simultaneously.'), Metasync::get_whitelabel_otto_name()), | |
| 844 | - sprintf(__('Contact %s support if rate limiting persists despite low crawl volume.'), Metasync::get_effective_plugin_name()) | |
| 893 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 894 | + sprintf(__('Frequent rate limiting can degrade %s SEO data delivery on your site.', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 895 | + __('Recommended Actions:', 'metasync'), | |
| 896 | + /* translators: 1: OTTO name (whitelabel), 2: effective plugin name (whitelabel-aware). */ | |
| 897 | + sprintf(__('Review your %1$s crawl frequency settings in the %2$s dashboard to reduce request volume.', 'metasync'), Metasync::get_whitelabel_otto_name(), Metasync::get_effective_plugin_name()), | |
| 898 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 899 | + sprintf(__('Check if multiple server processes are triggering %s jobs simultaneously.', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 900 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 901 | + sprintf(__('Contact %s support if rate limiting persists despite low crawl volume.', 'metasync'), Metasync::get_effective_plugin_name()) | |
| 845 | 902 | ); |
| 846 | 903 | |
| 847 | 904 | $description .= sprintf( |
| 848 | 905 | '<p>%s %s</p>', |
| 849 | - __( 'Quick link:' ), | |
| 850 | - $this->get_admin_link( '&tab=general', __( 'Review API Settings' ) ) | |
| 906 | + __( 'Quick link:', 'metasync' ), | |
| 907 | + $this->get_admin_link( '&tab=general', __( 'Review API Settings', 'metasync' ) ) | |
| 851 | 908 | ); |
| 852 | 909 | } |
| 853 | 910 | |
| 854 | 911 | return [ |
| @@ -913,9 +970,9 @@ | ||
| 913 | 970 | |
| 914 | 971 | // Good state: no debug constants active |
| 915 | 972 | if ( ! $any_debug_on ) { |
| 916 | 973 | return [ |
| 917 | - 'label' => __('Debug mode is disabled'), | |
| 974 | + 'label' => __('Debug mode is disabled', 'metasync'), | |
| 918 | 975 | 'status' => 'good', |
| 919 | 976 | 'badge' => [ |
| 920 | 977 | 'label' => Metasync::get_effective_plugin_name(), |
| 921 | 978 | 'color' => 'green', |
| @@ -921,9 +978,9 @@ | ||
| 921 | 978 | 'color' => 'green', |
| 922 | 979 | ], |
| 923 | 980 | 'description' => sprintf( |
| 924 | 981 | '<p>%s</p>', |
| 925 | - __('WordPress debug mode is not active. This is the recommended configuration for production sites.') | |
| 982 | + __('WordPress debug mode is not active. This is the recommended configuration for production sites.', 'metasync') | |
| 926 | 983 | ), |
| 927 | 984 | 'test' => 'metasync_debug_mode', |
| 928 | 985 | ]; |
| 929 | 986 | } |
| @@ -929,11 +986,11 @@ | ||
| 929 | 986 | } |
| 930 | 987 | |
| 931 | 988 | // Recommended state: one or more debug constants are active |
| 932 | 989 | if ( $stats['wp_debug_display'] ) { |
| 933 | - $label = __('Debug mode is enabled with error display active'); | |
| 990 | + $label = __('Debug mode is enabled with error display active', 'metasync'); | |
| 934 | 991 | } else { |
| 935 | - $label = __('Debug mode is enabled on this site'); | |
| 992 | + $label = __('Debug mode is enabled on this site', 'metasync'); | |
| 936 | 993 | } |
| 937 | 994 | |
| 938 | 995 | // Status table showing each flag's current state |
| 939 | 996 | $description = sprintf( |
| @@ -942,15 +999,15 @@ | ||
| 942 | 999 | '<li>%s <strong>%s</strong></li>' . |
| 943 | 1000 | '<li>%s <strong>%s</strong></li>' . |
| 944 | 1001 | '<li>%s <strong>%s</strong></li>' . |
| 945 | 1002 | '</ul>', |
| 946 | - __('Active Debug Configuration:'), | |
| 947 | - __('WP_DEBUG:'), | |
| 948 | - $stats['wp_debug'] ? __('Enabled') : __('Disabled'), | |
| 949 | - __('WP_DEBUG_LOG:'), | |
| 950 | - $stats['wp_debug_log'] ? __('Enabled') : __('Disabled'), | |
| 951 | - __('WP_DEBUG_DISPLAY:'), | |
| 952 | - $stats['wp_debug_display'] ? __('Enabled') : __('Disabled') | |
| 1003 | + __('Active Debug Configuration:', 'metasync'), | |
| 1004 | + __('WP_DEBUG:', 'metasync'), | |
| 1005 | + $stats['wp_debug'] ? __('Enabled', 'metasync') : __('Disabled', 'metasync'), | |
| 1006 | + __('WP_DEBUG_LOG:', 'metasync'), | |
| 1007 | + $stats['wp_debug_log'] ? __('Enabled', 'metasync') : __('Disabled', 'metasync'), | |
| 1008 | + __('WP_DEBUG_DISPLAY:', 'metasync'), | |
| 1009 | + $stats['wp_debug_display'] ? __('Enabled', 'metasync') : __('Disabled', 'metasync') | |
| 953 | 1010 | ); |
| 954 | 1011 | |
| 955 | 1012 | // Call out METASYNC_DEBUG if it is separately active |
| 956 | 1013 | if ( $stats['metasync_debug'] ) { |
| @@ -955,9 +1012,9 @@ | ||
| 955 | 1012 | // Call out METASYNC_DEBUG if it is separately active |
| 956 | 1013 | if ( $stats['metasync_debug'] ) { |
| 957 | 1014 | $description .= sprintf( |
| 958 | 1015 | '<p>%s</p>', |
| 959 | - __('The <code>METASYNC_DEBUG</code> constant is also active. This enables additional MetaSync diagnostic output.') | |
| 1016 | + __('The <code>METASYNC_DEBUG</code> constant is also active. This enables additional MetaSync diagnostic output.', 'metasync') | |
| 960 | 1017 | ); |
| 961 | 1018 | } |
| 962 | 1019 | |
| 963 | 1020 | // Escalated warning when WP_DEBUG_DISPLAY is on (errors visible to site visitors) |
| @@ -963,16 +1020,16 @@ | ||
| 963 | 1020 | // Escalated warning when WP_DEBUG_DISPLAY is on (errors visible to site visitors) |
| 964 | 1021 | if ( $stats['wp_debug_display'] ) { |
| 965 | 1022 | $description .= sprintf( |
| 966 | 1023 | '<p><strong>%s</strong> %s</p>', |
| 967 | - __('Warning:'), | |
| 968 | - __('WP_DEBUG_DISPLAY is active. PHP errors and notices may be visible to your site visitors, potentially exposing file paths, database details, and plugin internals. This should be disabled on any publicly accessible site.') | |
| 1024 | + __('Warning:', 'metasync'), | |
| 1025 | + __('WP_DEBUG_DISPLAY is active. PHP errors and notices may be visible to your site visitors, potentially exposing file paths, database details, and plugin internals. This should be disabled on any publicly accessible site.', 'metasync') | |
| 969 | 1026 | ); |
| 970 | 1027 | } |
| 971 | 1028 | |
| 972 | 1029 | $description .= sprintf( |
| 973 | 1030 | '<p><em>%s</em></p>', |
| 974 | - __('Debug mode is intended for development environments. On a production site, disabling it prevents information leakage and removes the performance overhead of error collection.') | |
| 1031 | + __('Debug mode is intended for development environments. On a production site, disabling it prevents information leakage and removes the performance overhead of error collection.', 'metasync') | |
| 975 | 1032 | ); |
| 976 | 1033 | |
| 977 | 1034 | $description .= sprintf( |
| 978 | 1035 | '<p><strong>%s</strong></p>' . |
| @@ -979,17 +1036,17 @@ | ||
| 979 | 1036 | '<ul>' . |
| 980 | 1037 | '<li>%s</li>' . |
| 981 | 1038 | '<li>%s</li>' . |
| 982 | 1039 | '</ul>', |
| 983 | - __('Recommended Actions:'), | |
| 984 | - __('Set <code>define(\'WP_DEBUG\', false);</code> in your wp-config.php if this is a live production site.'), | |
| 985 | - __('If error logging is needed in production, avoid WP_DEBUG_LOG — it writes to <code>wp-content/debug.log</code> which is publicly accessible via browser and can expose file paths, database details, and API keys. Use a dedicated logging solution that writes outside the webroot instead.') | |
| 1040 | + __('Recommended Actions:', 'metasync'), | |
| 1041 | + __('Set <code>define(\'WP_DEBUG\', false);</code> in your wp-config.php if this is a live production site.', 'metasync'), | |
| 1042 | + __('If error logging is needed in production, avoid WP_DEBUG_LOG — it writes to <code>wp-content/debug.log</code> which is publicly accessible via browser and can expose file paths, database details, and API keys. Use a dedicated logging solution that writes outside the webroot instead.', 'metasync') | |
| 986 | 1043 | ); |
| 987 | 1044 | |
| 988 | 1045 | $description .= sprintf( |
| 989 | 1046 | '<p>%s %s</p>', |
| 990 | - __( 'Quick link:' ), | |
| 991 | - $this->get_admin_link( '&tab=advanced', __( 'Advanced Settings' ) ) | |
| 1047 | + __( 'Quick link:', 'metasync' ), | |
| 1048 | + $this->get_admin_link( '&tab=advanced', __( 'Advanced Settings', 'metasync' ) ) | |
| 992 | 1049 | ); |
| 993 | 1050 | |
| 994 | 1051 | return [ |
| 995 | 1052 | 'label' => $label, |
| @@ -1017,15 +1074,15 @@ | ||
| 1017 | 1074 | { |
| 1018 | 1075 | // WP-Cron mode |
| 1019 | 1076 | $wp_cron_disabled = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON; |
| 1020 | 1077 | $wp_cron_mode = $wp_cron_disabled |
| 1021 | - ? __( 'System Cron (DISABLE_WP_CRON = true)' ) | |
| 1022 | - : __( 'WP-Cron (default)' ); | |
| 1078 | + ? __( 'System Cron (DISABLE_WP_CRON = true)', 'metasync' ) | |
| 1079 | + : __( 'WP-Cron (default)', 'metasync' ); | |
| 1023 | 1080 | |
| 1024 | 1081 | // PHP max execution time |
| 1025 | 1082 | $max_exec_raw = ini_get( 'max_execution_time' ); |
| 1026 | 1083 | $max_exec = $max_exec_raw === '0' || $max_exec_raw === 0 |
| 1027 | - ? __( 'Unlimited (0)' ) | |
| 1084 | + ? __( 'Unlimited (0)', 'metasync' ) | |
| 1028 | 1085 | : (int) $max_exec_raw . 's'; |
| 1029 | 1086 | |
| 1030 | 1087 | // Next scheduled transient cleanup |
| 1031 | 1088 | $next_cleanup_ts = wp_next_scheduled( 'metasync_cleanup_transients' ); |
| @@ -1030,9 +1087,9 @@ | ||
| 1030 | 1087 | // Next scheduled transient cleanup |
| 1031 | 1088 | $next_cleanup_ts = wp_next_scheduled( 'metasync_cleanup_transients' ); |
| 1032 | 1089 | $next_cleanup_val = $next_cleanup_ts |
| 1033 | 1090 | ? wp_date( 'Y-m-d H:i:s', $next_cleanup_ts ) . ' (in ' . human_time_diff( $next_cleanup_ts ) . ')' |
| 1034 | - : __( 'Not scheduled' ); | |
| 1091 | + : __( 'Not scheduled', 'metasync' ); | |
| 1035 | 1092 | |
| 1036 | 1093 | // Telemetry flush interval label |
| 1037 | 1094 | $flush_interval = Metasync_Telemetry_Config::QUEUE_FLUSH_INTERVAL; |
| 1038 | 1095 | $schedules = wp_get_schedules(); |
| @@ -1041,49 +1098,52 @@ | ||
| 1041 | 1098 | : $flush_interval; |
| 1042 | 1099 | |
| 1043 | 1100 | // OTTO suggestions cache TTL (stored in seconds, display as minutes) |
| 1044 | 1101 | $otto_cache_ttl_sec = Metasync_Otto_Config::get_otto_cache_ttl_seconds(); |
| 1045 | - $otto_cache_ttl_val = ( $otto_cache_ttl_sec / MINUTE_IN_SECONDS ) . ' ' . __( 'minutes' ); | |
| 1102 | + $otto_cache_ttl_val = ( $otto_cache_ttl_sec / MINUTE_IN_SECONDS ) . ' ' . __( 'minutes', 'metasync' ); | |
| 1046 | 1103 | |
| 1047 | 1104 | return [ |
| 1048 | 1105 | 'perf_wp_cron' => [ |
| 1049 | - 'label' => __( 'Performance - WP-Cron Mode' ), | |
| 1106 | + 'label' => __( 'Performance - WP-Cron Mode', 'metasync' ), | |
| 1050 | 1107 | 'value' => $wp_cron_mode, |
| 1051 | 1108 | ], |
| 1052 | 1109 | 'perf_php_max_exec' => [ |
| 1053 | - 'label' => __( 'Performance - PHP Max Execution Time' ), | |
| 1110 | + 'label' => __( 'Performance - PHP Max Execution Time', 'metasync' ), | |
| 1054 | 1111 | 'value' => $max_exec, |
| 1055 | 1112 | ], |
| 1056 | 1113 | 'perf_otto_request_timeout' => [ |
| 1057 | - 'label' => sprintf(__('Performance - %s API Request Timeout'), Metasync::get_whitelabel_otto_name()), | |
| 1114 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1115 | + 'label' => sprintf(__('Performance - %s API Request Timeout', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 1058 | 1116 | 'value' => '30s', |
| 1059 | 1117 | ], |
| 1060 | 1118 | 'perf_otto_cache_ttl' => [ |
| 1061 | - 'label' => sprintf(__('Performance - %s Suggestions Cache TTL'), Metasync::get_whitelabel_otto_name()), | |
| 1119 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1120 | + 'label' => sprintf(__('Performance - %s Suggestions Cache TTL', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 1062 | 1121 | 'value' => $otto_cache_ttl_val, |
| 1063 | 1122 | ], |
| 1064 | 1123 | 'perf_otto_max_calls' => [ |
| 1065 | - 'label' => sprintf(__('Performance - %s Max API Calls/Min'), Metasync::get_whitelabel_otto_name()), | |
| 1124 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1125 | + 'label' => sprintf(__('Performance - %s Max API Calls/Min', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 1066 | 1126 | 'value' => Metasync_Otto_Transient_Cache::MAX_API_CALLS_PER_MINUTE, |
| 1067 | 1127 | ], |
| 1068 | 1128 | 'perf_telemetry_queue_max' => [ |
| 1069 | - 'label' => __( 'Performance - Telemetry Max Queue Size' ), | |
| 1129 | + 'label' => __( 'Performance - Telemetry Max Queue Size', 'metasync' ), | |
| 1070 | 1130 | 'value' => Metasync_Telemetry_Config::MAX_QUEUE_SIZE, |
| 1071 | 1131 | ], |
| 1072 | 1132 | 'perf_telemetry_batch' => [ |
| 1073 | - 'label' => __( 'Performance - Telemetry Batch Size' ), | |
| 1133 | + 'label' => __( 'Performance - Telemetry Batch Size', 'metasync' ), | |
| 1074 | 1134 | 'value' => Metasync_Telemetry_Config::QUEUE_BATCH_SIZE, |
| 1075 | 1135 | ], |
| 1076 | 1136 | 'perf_telemetry_flush' => [ |
| 1077 | - 'label' => __( 'Performance - Telemetry Queue Flush Interval' ), | |
| 1137 | + 'label' => __( 'Performance - Telemetry Queue Flush Interval', 'metasync' ), | |
| 1078 | 1138 | 'value' => $flush_interval_label, |
| 1079 | 1139 | ], |
| 1080 | 1140 | 'perf_api_max_retries' => [ |
| 1081 | - 'label' => __( 'Performance - API Max Retry Attempts' ), | |
| 1141 | + 'label' => __( 'Performance - API Max Retry Attempts', 'metasync' ), | |
| 1082 | 1142 | 'value' => Metasync_Telemetry_Config::MAX_RETRY_ATTEMPTS, |
| 1083 | 1143 | ], |
| 1084 | 1144 | 'perf_next_cleanup' => [ |
| 1085 | - 'label' => __( 'Performance - Next Transient Cleanup' ), | |
| 1145 | + 'label' => __( 'Performance - Next Transient Cleanup', 'metasync' ), | |
| 1086 | 1146 | 'value' => $next_cleanup_val, |
| 1087 | 1147 | ], |
| 1088 | 1148 | ]; |
| 1089 | 1149 | } |
| @@ -1132,23 +1192,26 @@ | ||
| 1132 | 1192 | $last_hit = $stats['last_hit']; |
| 1133 | 1193 | |
| 1134 | 1194 | $last_hit_text = $last_hit |
| 1135 | 1195 | ? sprintf( |
| 1136 | - __( 'Last failure: %s' ), | |
| 1196 | + /* translators: %s: date and time of the last failure. */ | |
| 1197 | + __( 'Last failure: %s', 'metasync' ), | |
| 1137 | 1198 | date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $last_hit ) |
| 1138 | 1199 | ) |
| 1139 | - : __( 'No failed actions recorded in the last 24 hours.' ); | |
| 1200 | + : __( 'No failed actions recorded in the last 24 hours.', 'metasync' ); | |
| 1140 | 1201 | |
| 1141 | 1202 | if ( $count > self::FAILED_ACTIONS_THRESHOLD ) { |
| 1142 | 1203 | $status = 'recommended'; |
| 1143 | 1204 | $label = sprintf( |
| 1144 | - __( '%s has %d failed SEO processing actions in the last 24 hours' ), | |
| 1205 | + /* translators: 1: effective plugin name (whitelabel-aware), 2: number of failed actions. */ | |
| 1206 | + __( '%1$s has %2$d failed SEO processing actions in the last 24 hours', 'metasync' ), | |
| 1145 | 1207 | Metasync::get_effective_plugin_name(), |
| 1146 | 1208 | $count |
| 1147 | 1209 | ); |
| 1148 | 1210 | } else { |
| 1149 | 1211 | $status = 'good'; |
| 1150 | - $label = sprintf(__('%s SEO action queue is healthy'), Metasync::get_effective_plugin_name()); | |
| 1212 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 1213 | + $label = sprintf(__('%s SEO action queue is healthy', 'metasync'), Metasync::get_effective_plugin_name()); | |
| 1151 | 1214 | } |
| 1152 | 1215 | |
| 1153 | 1216 | $description = sprintf( |
| 1154 | 1217 | '<p><strong>%s</strong></p>' . |
| @@ -1155,10 +1218,12 @@ | ||
| 1155 | 1218 | '<ul>' . |
| 1156 | 1219 | '<li>%s <strong>%d</strong></li>' . |
| 1157 | 1220 | '<li>%s</li>' . |
| 1158 | 1221 | '</ul>', |
| 1159 | - sprintf(__('%s Failed Actions Statistics (last 24 hours):'), Metasync::get_effective_plugin_name()), | |
| 1160 | - sprintf(__('Failed %s SEO processing jobs:'), Metasync::get_whitelabel_otto_name()), | |
| 1222 | + /* translators: %s: effective plugin name (whitelabel-aware). */ | |
| 1223 | + sprintf(__('%s Failed Actions Statistics (last 24 hours):', 'metasync'), Metasync::get_effective_plugin_name()), | |
| 1224 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1225 | + sprintf(__('Failed %s SEO processing jobs:', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 1161 | 1226 | $count, |
| 1162 | 1227 | $last_hit_text |
| 1163 | 1228 | ); |
| 1164 | 1229 | |
| @@ -1164,9 +1229,10 @@ | ||
| 1164 | 1229 | |
| 1165 | 1230 | if ( $status === 'good' ) { |
| 1166 | 1231 | $description .= sprintf( |
| 1167 | 1232 | '<p><em>%s</em></p>', |
| 1168 | - sprintf(__('%s SEO processing jobs are completing successfully. No action required.'), Metasync::get_whitelabel_otto_name()) | |
| 1233 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1234 | + sprintf(__('%s SEO processing jobs are completing successfully. No action required.', 'metasync'), Metasync::get_whitelabel_otto_name()) | |
| 1169 | 1235 | ); |
| 1170 | 1236 | } else { |
| 1171 | 1237 | $description .= sprintf( |
| 1172 | 1238 | '<p><strong>%s</strong></p>' . |
| @@ -1174,19 +1240,22 @@ | ||
| 1174 | 1240 | '<li>%s</li>' . |
| 1175 | 1241 | '<li>%s</li>' . |
| 1176 | 1242 | '<li>%s</li>' . |
| 1177 | 1243 | '</ul>', |
| 1178 | - __( 'Recommended Actions:' ), | |
| 1179 | - sprintf(__('Check your %1$s API connection in %1$s → Settings.'), Metasync::get_effective_plugin_name()), | |
| 1180 | - sprintf(__('Review your PHP error log for %s processing exceptions.'), Metasync::get_whitelabel_otto_name()), | |
| 1181 | - sprintf(__('Verify your %1$s UUID is correctly configured and the %2$s API is reachable.'), Metasync::get_whitelabel_otto_name(), Metasync::get_effective_plugin_name()) | |
| 1244 | + __( 'Recommended Actions:', 'metasync' ), | |
| 1245 | + /* translators: 1: effective plugin name (whitelabel-aware). */ | |
| 1246 | + sprintf(__('Check your %1$s API connection in %1$s → Settings.', 'metasync'), Metasync::get_effective_plugin_name()), | |
| 1247 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1248 | + sprintf(__('Review your PHP error log for %s processing exceptions.', 'metasync'), Metasync::get_whitelabel_otto_name()), | |
| 1249 | + /* translators: 1: OTTO name (whitelabel), 2: effective plugin name (whitelabel-aware). */ | |
| 1250 | + sprintf(__('Verify your %1$s UUID is correctly configured and the %2$s API is reachable.', 'metasync'), Metasync::get_whitelabel_otto_name(), Metasync::get_effective_plugin_name()) | |
| 1182 | 1251 | ); |
| 1183 | 1252 | |
| 1184 | 1253 | $description .= sprintf( |
| 1185 | 1254 | '<p>%s %s · %s</p>', |
| 1186 | - __( 'Quick links:' ), | |
| 1187 | - $this->get_admin_link( '&tab=general', __( 'Review API Settings' ) ), | |
| 1188 | - $this->get_admin_link( '-sync-log', __( 'View Changes Log' ) ) | |
| 1255 | + __( 'Quick links:', 'metasync' ), | |
| 1256 | + $this->get_admin_link( '&tab=general', __( 'Review API Settings', 'metasync' ) ), | |
| 1257 | + $this->get_admin_link( '-sync-log', __( 'View Changes Log', 'metasync' ) ) | |
| 1189 | 1258 | ); |
| 1190 | 1259 | } |
| 1191 | 1260 | |
| 1192 | 1261 | return [ |
| @@ -1198,6 +1267,126 @@ | ||
| 1198 | 1267 | ], |
| 1199 | 1268 | 'description' => $description, |
| 1200 | 1269 | 'test' => 'metasync_failed_actions', |
| 1201 | 1270 | ]; |
| 1271 | + } | |
| 1272 | + | |
| 1273 | + /** | |
| 1274 | + * Site Health test for OTTO crawl-notify background job reliability | |
| 1275 | + * | |
| 1276 | + * Reads the bounded per-URL status store (Metasync_Otto_Job_Status) that | |
| 1277 | + * the crawl-notify pipeline writes as its background jobs run, so an | |
| 1278 | + * administrator can see what actually happened to notified URLs — not just | |
| 1279 | + * that the webhook was acknowledged. | |
| 1280 | + * | |
| 1281 | + * Status levels: | |
| 1282 | + * - good: no failed URLs and fewer than the threshold stuck retrying | |
| 1283 | + * - recommended: failed URLs exist or retrying count exceeds the threshold | |
| 1284 | + * | |
| 1285 | + * When WP-Cron is disabled (DISABLE_WP_CRON) without a visible system | |
| 1286 | + * crontab entry the pipeline cannot run at all, so an advisory is always | |
| 1287 | + * included in that case. | |
| 1288 | + * | |
| 1289 | + * @since 1.0.0 | |
| 1290 | + * @return array Site Health test result | |
| 1291 | + */ | |
| 1292 | + public function otto_job_reliability_check() | |
| 1293 | + { | |
| 1294 | + $otto_name = Metasync::get_whitelabel_otto_name(); | |
| 1295 | + | |
| 1296 | + if ( ! class_exists( 'Metasync_Otto_Job_Status' ) ) { | |
| 1297 | + return [ | |
| 1298 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1299 | + 'label' => sprintf( __( '%s crawl job tracking is unavailable', 'metasync' ), $otto_name ), | |
| 1300 | + 'status' => 'good', | |
| 1301 | + 'badge' => [ | |
| 1302 | + 'label' => Metasync::get_effective_plugin_name(), | |
| 1303 | + 'color' => 'green', | |
| 1304 | + ], | |
| 1305 | + 'description' => '<p>' . esc_html__( 'The status store class is not loaded; nothing to report.', 'metasync' ) . '</p>', | |
| 1306 | + 'test' => 'metasync_otto_job_reliability', | |
| 1307 | + ]; | |
| 1308 | + } | |
| 1309 | + | |
| 1310 | + $counts = Metasync_Otto_Job_Status::counts(); | |
| 1311 | + | |
| 1312 | + $retrying_threshold = 25; | |
| 1313 | + if ( $counts['failed'] > 0 || $counts['retrying'] > $retrying_threshold ) { | |
| 1314 | + $status = 'recommended'; | |
| 1315 | + $label = sprintf( | |
| 1316 | + /* translators: 1: OTTO name (whitelabel), 2: number of failed jobs, 3: number of retrying jobs. */ | |
| 1317 | + __( '%1$s crawl jobs need attention (%2$d failed, %3$d retrying)', 'metasync' ), | |
| 1318 | + $otto_name, | |
| 1319 | + $counts['failed'], | |
| 1320 | + $counts['retrying'] | |
| 1321 | + ); | |
| 1322 | + } else { | |
| 1323 | + $status = 'good'; | |
| 1324 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1325 | + $label = sprintf( __( '%s crawl jobs are completing normally', 'metasync' ), $otto_name ); | |
| 1326 | + } | |
| 1327 | + | |
| 1328 | + $description = sprintf( | |
| 1329 | + '<p><strong>%s</strong></p><ul><li>%s <strong>%d</strong></li><li>%s <strong>%d</strong></li><li>%s <strong>%d</strong></li><li>%s <strong>%d</strong></li><li>%s <strong>%d</strong></li></ul>', | |
| 1330 | + /* translators: %s: OTTO name (whitelabel). */ | |
| 1331 | + sprintf( __( '%s crawl job status (last 48 hours):', 'metasync' ), $otto_name ), | |
| 1332 | + __( 'Accepted, awaiting run:', 'metasync' ), | |
| 1333 | + $counts['accepted'], | |
| 1334 | + __( 'Retrying after transient failures:', 'metasync' ), | |
| 1335 | + $counts['retrying'], | |
| 1336 | + __( 'Completed:', 'metasync' ), | |
| 1337 | + $counts['completed'], | |
| 1338 | + __( 'Failed (retries exhausted):', 'metasync' ), | |
| 1339 | + $counts['failed'], | |
| 1340 | + __( 'Queued past the per-batch cap:', 'metasync' ), | |
| 1341 | + $counts['pending'] | |
| 1342 | + ); | |
| 1343 | + | |
| 1344 | + if ( $this->constant_is_truthy( 'DISABLE_WP_CRON' ) ) { | |
| 1345 | + $description .= sprintf( | |
| 1346 | + '<p><strong>%s</strong> %s</p>', | |
| 1347 | + __( 'WP-Cron is disabled on this site.', 'metasync' ), | |
| 1348 | + sprintf( | |
| 1349 | + /* translators: %s: OTTO product name */ | |
| 1350 | + __( 'Background jobs only run if a system crontab (or equivalent) calls wp-cron.php. Without it, %s crawl notifications are queued but never processed.', 'metasync' ), | |
| 1351 | + $otto_name | |
| 1352 | + ) | |
| 1353 | + ); | |
| 1354 | + } | |
| 1355 | + | |
| 1356 | + if ( $status !== 'good' ) { | |
| 1357 | + $description .= sprintf( | |
| 1358 | + '<p>%s %s · %s</p>', | |
| 1359 | + __( 'Quick links:', 'metasync' ), | |
| 1360 | + $this->get_admin_link( '&tab=general', __( 'Review API Settings', 'metasync' ) ), | |
| 1361 | + $this->get_admin_link( '-sync-log', __( 'View Changes Log', 'metasync' ) ) | |
| 1362 | + ); | |
| 1363 | + } | |
| 1364 | + | |
| 1365 | + return [ | |
| 1366 | + 'label' => $label, | |
| 1367 | + 'status' => $status, | |
| 1368 | + 'badge' => [ | |
| 1369 | + 'label' => Metasync::get_effective_plugin_name(), | |
| 1370 | + 'color' => $status === 'recommended' ? 'orange' : 'green', | |
| 1371 | + ], | |
| 1372 | + 'description' => $description, | |
| 1373 | + 'test' => 'metasync_otto_job_reliability', | |
| 1374 | + ]; | |
| 1375 | + } | |
| 1376 | + | |
| 1377 | + /** | |
| 1378 | + * Whether a named constant is defined and evaluates truthy. | |
| 1379 | + * | |
| 1380 | + * The constant name arrives as data so the value is resolved through | |
| 1381 | + * constant() at runtime; some constants are also loaded from WP stubs | |
| 1382 | + * with fixed values, which makes a direct `defined() && CONST` check | |
| 1383 | + * statically redundant even though the live value varies per site. | |
| 1384 | + * | |
| 1385 | + * @since 1.0.0 | |
| 1386 | + * @param string $name Constant name, without the leading backslash. | |
| 1387 | + * @return bool | |
| 1388 | + */ | |
| 1389 | + private function constant_is_truthy( $name ) { | |
| 1390 | + return defined( $name ) && filter_var( constant( $name ), FILTER_VALIDATE_BOOLEAN ); | |
| 1202 | 1391 | } |
| 1203 | 1392 | } |