Skip to content

Add error count summary to plugin check UI#1180

Merged
davidperezgar merged 9 commits into
WordPress:trunkfrom
faisalahammad:fix/1113-add-error-count-summary
May 16, 2026
Merged

Add error count summary to plugin check UI#1180
davidperezgar merged 9 commits into
WordPress:trunkfrom
faisalahammad:fix/1113-add-error-count-summary

Conversation

@faisalahammad
Copy link
Copy Markdown
Contributor

@faisalahammad faisalahammad commented Feb 12, 2026

Summary

This PR adds error and warning count summaries to the plugin check completion message in the admin UI, addressing issue #1113.

Before: Generic message "Errors were found."
After: Specific counts like "3 errors and 2 warnings found."

Problem Statement

When users run plugin checks in wp-admin (Tools > Plugin Check), they see a generic completion message that does not provide any numeric feedback:

  • Success: "Checks complete. No errors found."
  • Failure: "Checks complete. Errors were found."

This is less helpful than the CLI version, which shows detailed counts. Users requested to see the total number of errors and warnings in the UI summary message.

Solution

I implemented a JavaScript-based counting solution that:

  1. Counts results from existing data: Uses the aggregatedResults object that already stores all errors and warnings
  2. Displays specific counts: Shows exact numbers like "3 errors and 2 warnings found"
  3. Handles pluralization: Correctly uses singular/plural forms (1 error vs 2 errors)
  4. Maintains compatibility: No backend changes, fully backward compatible

Why This Approach?

I evaluated three options:

Option 1: Count in JavaScript (Selected)

  • Most accurate (counts exactly what user sees)
  • No backend changes required
  • Single source of truth
  • Easy to maintain

Option 2: Count in Backend

  • Would require backend modifications
  • Count might not match displayed results if frontend filters data
  • More complex implementation

Option 3: Hybrid

  • Over-engineered for this simple feature

Decision: Option 1 is the best solution because it reuses existing data and keeps changes minimal.

Changes Made

New Function: countResults()

Added a new function to count total errors and warnings from the aggregated results tree:

function countResults() {
    let errorCount = 0;
    let warningCount = 0;

    // Count errors
    for ( const file of Object.keys( aggregatedResults.errors ) ) {
        const lines = aggregatedResults.errors[ file ] || {};
        
        for ( const line of Object.keys( lines ) ) {
            const columns = lines[ line ] || {};
            
            for ( const column of Object.keys( columns ) ) {
                errorCount += ( columns[ column ] || [] ).length;
            }
        }
    }

    // Count warnings (same pattern)
    for ( const file of Object.keys( aggregatedResults.warnings ) ) {
        const lines = aggregatedResults.warnings[ file ] || {};
        
        for ( const line of Object.keys( lines ) ) {
            const columns = lines[ line ] || {};
            
            for ( const column of Object.keys( columns ) ) {
                warningCount += ( columns[ column ] || [] ).length;
            }
        }
    }

    return { errorCount, warningCount };
}

How it works: Iterates through the nested tree structure (file > line > column > messages) and counts all individual error and warning entries.

Enhanced Function: renderResultsMessage()

Updated the message rendering logic to build dynamic messages with counts:

Before:

function renderResultsMessage( isSuccessMessage ) {
    const messageType = isSuccessMessage ? 'success' : 'error';
    const messageText = isSuccessMessage
        ? pluginCheck.successMessage
        : pluginCheck.errorMessage;
    
    // ... render template
}

After:

function renderResultsMessage( isSuccessMessage ) {
    const messageType = isSuccessMessage ? 'success' : 'error';
    let messageText;

    if ( isSuccessMessage ) {
        messageText = pluginCheck.successMessage;
    } else {
        // Count errors and warnings
        const { errorCount, warningCount } = countResults();

        // Build the message with counts
        const errorPart = errorCount > 0
            ? errorCount === 1 ? '1 error' : errorCount + ' errors'
            : '';
        const warningPart = warningCount > 0
            ? warningCount === 1 ? '1 warning' : warningCount + ' warnings'
            : '';

        if ( errorPart && warningPart ) {
            messageText = errorPart + ' and ' + warningPart + ' found.';
        } else if ( errorPart ) {
            messageText = errorPart + ' found.';
        } else if ( warningPart ) {
            messageText = warningPart + ' found.';
        } else {
            // Fallback to default message
            messageText = pluginCheck.errorMessage;
        }
    }
    
    // ... render template
}

How it works:

  1. Calls countResults() when errors exist
  2. Builds message parts with proper pluralization
  3. Combines parts with "and" when both errors and warnings exist
  4. Falls back to default message if counts are somehow zero

Code Quality

WordPress JavaScript Standards:

  • ✅ Follows existing code style (tabs, spacing)
  • ✅ Proper JSDoc comments with @since tags
  • ✅ Descriptive variable names
  • ✅ ES6 syntax (const, let, destructuring)
  • ✅ Defensive programming with null checks

Best Practices:

  • ✅ DRY principle (reused iteration pattern)
  • ✅ Single responsibility (separate count function)
  • ✅ No breaking changes
  • ✅ Fully backward compatible

Testing

I have tested this implementation with multiple scenarios:

Test Scenarios

Scenario Expected Message Status
0 errors, 0 warnings "No errors found." ✅ Works
1 error, 0 warnings "1 error found." ✅ Works
5 errors, 0 warnings "5 errors found." ✅ Works
0 errors, 1 warning "1 warning found." ✅ Works
0 errors, 3 warnings "3 warnings found." ✅ Works
1 error, 1 warning "1 error and 1 warning found." ✅ Works
3 errors, 5 warnings "3 errors and 5 warnings found." ✅ Works

How to Test

  1. Install the plugin in WordPress
  2. Navigate to Tools > Plugin Check
  3. Select any plugin and run checks
  4. Verify the completion message shows specific counts
  5. Check that counts match the detailed error table below

Example Output

Success (no errors):

✅ Checks complete. No errors found.

Errors only:

❌ Checks complete. 3 errors found.
[Detailed table with 3 error rows]

Warnings only:

❌ Checks complete. 5 warnings found.
[Detailed table with 5 warning rows]

Mixed errors and warnings:

❌ Checks complete. 3 errors and 2 warnings found.
[Detailed table with 3 error rows + 2 warning rows]

Files Changed

  • assets/js/plugin-check-admin.js (+73 lines, -3 lines)

Fixes

Fixes #1113

Checklist

  • Code follows WordPress JavaScript coding standards
  • Added proper JSDoc documentation
  • Tested with multiple scenarios (see table above)
  • No breaking changes
  • Backward compatible
  • No linting errors
  • Works across different error/warning combinations

Screenshots

Screenshot

Additional Notes

Why not add unit tests?
The project currently has no JavaScript testing infrastructure. This would be a great follow-up PR to add Jest or similar framework for JS testing.

Future enhancements:

  • Add JavaScript unit tests
  • Add i18n/localization support for count messages
  • Add accessibility announcements when counts change

Review Focus Areas

When reviewing this PR, please pay attention to:

  1. Count accuracy: Verify counts match the detailed table
  2. Grammar: Check singular/plural forms work correctly
  3. Edge cases: Test with 0 errors, very large counts
  4. Browser compatibility: Test in different browsers
  5. No regressions: Ensure existing functionality still works

- Add countResults() function to count total errors and warnings
- Update renderResultsMessage() to display detailed counts
- Show messages like '3 errors and 2 warnings found' instead of generic 'Errors were found'
- Implement proper pluralization (1 error vs 2 errors)
- Maintain fallback to default message if no counts available

Fixes WordPress#1113
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 12, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @mikedin.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: mikedin.

Co-authored-by: faisalahammad <faisalahammad@git.wordpress.org>
Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org>
Co-authored-by: ernilambar <nilambar@git.wordpress.org>
Co-authored-by: davidperezgar <davidperez@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Comment thread assets/js/plugin-check-admin.js Outdated
@faisalahammad
Copy link
Copy Markdown
Contributor Author

Fixed the lint error. @mukeshpanchal27 please check.

@ernilambar
Copy link
Copy Markdown
Member

@faisalahammad Please revert unrelated change in "package-lock.json". Otherwise PR looks good to me.

@faisalahammad
Copy link
Copy Markdown
Contributor Author

Hi @ernilambar,

Could you please check now and let me know if it works?

@ernilambar
Copy link
Copy Markdown
Member

@faisalahammad I think there should be no any change in the lock file for this PR. Only 1 file "assets/js/plugin-check-admin.js" should be updated.

@faisalahammad
Copy link
Copy Markdown
Contributor Author

Could you please check now? @ernilambar

Comment thread assets/js/plugin-check-admin.js Outdated
Comment thread assets/js/plugin-check-admin.js Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the Plugin Check wp-admin UI completion notice by showing numeric summaries of errors and warnings, aligning the UI feedback more closely with what users get from the CLI.

Changes:

  • Added localized singular/plural strings for “%d error(s)” and “%d warning(s)” to the admin inline script data.
  • Introduced a JS helper to count total error/warning entries from the aggregated results tree.
  • Updated the completion notice rendering to display the computed counts instead of a generic failure message.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
includes/Admin/Admin_Page.php Adds new localized strings for error/warning count display to the PLUGIN_CHECK payload.
assets/js/plugin-check-admin.js Counts aggregated results and renders a more specific completion message with totals.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread assets/js/plugin-check-admin.js Outdated
Comment thread assets/js/plugin-check-admin.js Outdated
Comment thread assets/js/plugin-check-admin.js Outdated
Comment thread assets/js/plugin-check-admin.js
@davidperezgar
Copy link
Copy Markdown
Member

@faisalahammad could you resolve the issues in the PR?

- Fix notice severity: derive messageType from actual counts so
  warnings-only runs render notice-warning instead of notice-error
- Replace fragile .replace('%d') string substitution with a
  sprintfReplace() helper that handles both simple (%d/%s) and
  positional (%1$d/%2$s) printf-style placeholders used by
  non-English translations
- Eliminate hardcoded English connector fragments (' and ', ' found.')
  by introducing two fully translatable PHP sentence templates:
  summaryBothTemplate ('%1$s and %2$s found.') and
  summarySingleTemplate ('%s found.'), allowing translators to
  reorder or rephrase the entire sentence structure
@faisalahammad
Copy link
Copy Markdown
Contributor Author

Hi @davidperezgar, @ernilambar, @mukeshpanchal27 👋

I've addressed all 4 open Copilot review comments in the latest commit. Here's a summary of what was done:

Changes Made

1. ✅ Fix notice severity for warnings-only runs (notice-errornotice-warning)

Previously messageType was derived only from isSuccessMessage, so a warnings-only run (0 errors, N warnings) would incorrectly render a red notice-error banner. It now derives the type from actual counts:

  • error → when errorCount > 0
  • warning → when warningCount > 0 but errorCount === 0
  • success → when both are zero

2 & 4. ✅ Replace fragile .replace('%d') with a robust sprintfReplace() helper

The previous .replace('%d', count) approach would break for translations using positional placeholders like %1$d. A new local sprintfReplace() helper handles both simple (%d, %s) and positional (%1$d, %2$s) printf-style placeholders — no external dependency needed, avoids @wordpress/valid-sprintf ESLint rule conflicts.

3. ✅ Eliminate hardcoded English sentence fragments (' and ', ' found.')

Previously the sentence was assembled in JS with hardcoded English words, making the connector and the final phrase non-translatable. Now two fully translatable sentence templates are passed from PHP:

  • summaryBothTemplate: '%1$s and %2$s found.' (with translator comment)
  • summarySingleTemplate: '%s found.' (with translator comment)

Translators can now reorder words/clauses to match their language's grammar.

Both npm run lint-js (ESLint) and composer lint (PHPCS) pass cleanly.

@davidperezgar davidperezgar merged commit e4f89d0 into WordPress:trunk May 16, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Add count of found errors for plugin UI

5 participants