Skip to content

Report core font health in the System Report and Site Health - #2010

Merged
jakejackson1 merged 1 commit into
developmentfrom
feature/font-health-reporting
Nov 10, 2026
Merged

jakejackson1 merged 1 commit into
developmentfrom
feature/font-health-reporting

Conversation

@gravitypdf-bot

@gravitypdf-bot gravitypdf-bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A font that gave up after its retry showed only in the admin notice, which can be dismissed for good, and a site with core font downloads turned off read as broken ("0 of 4 required files installed"). This adds two System Report rows and a Site Health test so both show up for support, and the failure reports clear themselves once the fonts are on disk.

  • Adds a "Core Fonts failed" System Report row listing the files that gave up and when, or None. Dismissing the notice doesn't hide them.
  • Forgets a give-up once its font is on disk, so a font copied in by hand also drops out of the admin notice and the row.
  • Adds a "Core Font downloads" System Report row: On, Off (GPDF_AUTO_INSTALL_FONTS constant), or Off / Partly off (gfpdf_auto_install_fonts filter).
  • Adds the Site Health test gravity_pdf_core_fonts, for users with gravityforms_view_settings. It is critical when a missing required file gave up and recommended when downloads are only turned off, and names the files and the cause.
  • Sends the admin notice's report button and the Site Health report link straight to the relevant row: "Core Fonts failed", or "Core Font downloads" when downloads are only turned off.
  • Missing files still waiting on the background sync stay good.
  • No new options, transients or HTTP requests.

Try it

Add this to an mu-plugin on a wp-env site and pick a core font (e.g. Free Serif) as the default font:

<?php
add_filter( 'gfpdf_auto_install_fonts', '__return_false' );
  1. Open Forms → System Status. Under Gravity PDF → Directories and Permissions, "Core Font downloads" reads Off (gfpdf_auto_install_fonts filter) and "Core Fonts failed" reads None.
  2. Open Tools → Site Health. "Some core fonts your PDFs need are missing" is listed as recommended. It names the FreeSerif files and the filter.
  3. Remove the filter, let cron download the fonts, and reload Site Health. The test is now under Passed tests.
  4. To check the failed row, return a WP_Error from pre_http_request, save the settings, and run cron twice past the retry. "Core Fonts failed" lists the files with their dates, and still does after you dismiss the admin notice. If the font is one the site requires, Site Health lists "Gravity PDF could not download required fonts" as critical.
  5. Copy one of those files into wp-content/uploads/PDF_EXTENDED_TEMPLATES/fonts/ by hand and reload. It no longer appears in "Core Fonts failed" or the admin notice.

Test plan

  • The System Report, actions and font PHPUnit classes pass on single site (491 tests) and multisite (466 tests), apart from three failures that only happen in the local worktree harness: test_an_unwritable_folder_fails_without_a_request x2 (the container runs as root) and test_the_kill_switch_constant_turns_downloads_off (a shim warning)
  • PHPCS and PHPStan clean
  • CI is green
More info
  • Model_Font_Downloader gains public get_auto_install_status(), get_auto_install_blocker( array $missing ): ?string and is_auto_install_overridden(), and Model_Required_Fonts gains public get_missing_files(), all @since 6.19.0.
  • The blocker runs the existing can_download_all(), so Site Health and the downloader can't disagree. It is null when nothing missing is blocked, which includes an empty list.
  • get_auto_install_status() asks about every file on the manifest, so a site that blocks every download never reads On just because nothing is missing. That also keeps the row stable in the E2E screenshot, where other specs' forms decide what is required. With a callback hooked, the filter runs once per manifest file, only when the report is built. With none it returns On without the walk.
  • Direct Site Health tests block the page, and finding the missing files scans every form. Model_System_Report::get_core_font_health() skips that scan unless a file has given up or is_auto_install_overridden() says a download could be blocked, as the result is good otherwise. A site with any gfpdf_auto_install_fonts callback still scans.
  • get_missing_files() asks Model_Font_Sources::is_installed(), the same check as the "Core Fonts installed" counts, so a required font that another font's file holds the name of counts as missing until its hashed copy is saved.
  • "Core Fonts failed" reads get_failed_files(), including on a subsite, where it lists the main network's record.
  • Model_Font_Downloader::get_failures() deletes a give-up and its back-off when is_installed() finds the file, once per request and only for files that gave up. If the font goes missing again it starts over with a new retry. is_installed() compares size only, so another font's file of exactly the right size counts as installed.
  • A give-up for a font no form needs any more stays in the row and the notice, as finding that scans every form. The Site Health test only counts files that are still missing, so it ignores those.
  • Model_System_Report gains an optional trailing ?Model_Font_Downloader $font_downloader = null constructor argument, which falls back to the registered downloader.
  • Model_Font_Sources::get_manifest() now builds its copy with the hashed names once, and rebuilds it only when the collisions change, rather than copying on every read. It compares the collisions because get_known_builds() calls it while they are part built.
  • The core fonts docs URL and the fallback font sentence live once in View_Actions, which the Site Health test reads, so a copy edit is made in one place. The same goes for the bulleted font list, View_Actions::get_code_list().
  • Gravity Forms gives report rows no ID but echoes their labels unescaped, so the two font rows carry their anchors in the label, as the section heading already does. The export reads label_export, so its text is unchanged.
  • The filter docs link (https://docs.gravitypdf.com/developers/filters/gfpdf_auto_install_fonts/) needs a matching docs page.

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Coverage report for commit: 50ee553
File: ./tmp/jest-coverage/clover.xml

Cover ┌─────────────────────────┐ Freq.
   0% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  10% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  20% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  30% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  40% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  50% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  60% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  70% │ █░░░░░░░░░░░░░░░░░░░░░░ │  3.1%
  80% │ ██░░░░░░░░░░░░░░░░░░░░░ │  4.7%
  90% │ ██████░░░░░░░░░░░░░░░░░ │ 18.8%
 100% │ ███████████████████████ │ 73.4%
      └─────────────────────────┘
 *Legend:* █ = Current Distribution 
Summary - Lines: 93.99% | Methods: 90.96% | Branches: 85.58%
FilesLinesMethodsBranches
src/assets/js/react/actions
   fontManager.js97.92%91.67%100.00%
   templates.js100.00%100.00%100.00%
src/assets/js/react/components/Alert
   Alert.js100.00%100.00%100.00%
src/assets/js/react/components
   CustomHashRouter.js100.00%100.00%100.00%
   Empty.js100.00%100.00%100.00%
   ShowMessage.js80.65%80.00%72.22%
   Spinner.js100.00%100.00%100.00%
src/assets/js/react/components/FontManager
   AddFont.js100.00%100.00%100.00%
   AddUpdateFontFooter.js100.00%100.00%91.67%
   AdvancedButton.js100.00%100.00%100.00%
   DeleteConfirm.js90.91%75.00%100.00%
   FontDeleteButton.js100.00%80.00%100.00%
   FontDetail.js100.00%100.00%100.00%
   FontInstallButton.js100.00%66.67%100.00%
   FontList.js100.00%50.00%65.22%
   FontListAlertMessage.js100.00%100.00%100.00%
   FontListItems.js96.00%83.33%88.24%
   FontListSkeleton.js100.00%100.00%100.00%
   FontManager.js73.68%50.00%50.00%
   FontManagerBody.js89.12%90.32%84.96%
   FontManagerHeader.js100.00%100.00%25.00%
   FontPreview.js100.00%100.00%100.00%
   FontStatus.js100.00%66.67%100.00%
   FontUsage.js100.00%66.67%100.00%
   FontVariant.js94.12%80.00%90.24%
   FontVariantLabel.js100.00%100.00%100.00%
   Icon.js100.00%100.00%100.00%
   InitialAddUpdateState.js100.00%100.00%100.00%
   SearchBox.js90.00%66.67%69.23%
   TemplateTooltip.js100.00%100.00%100.00%
   UpdateFont.js75.00%50.00%64.29%
src/assets/js/react/components/Modal
   CloseDialog.js93.33%66.67%70.59%
src/assets/js/react/components/Template
   TemplateActivateButton.js100.00%100.00%100.00%
   TemplateButton.js85.71%66.67%100.00%
   TemplateContainer.js71.43%66.67%25.00%
   TemplateDeleteButton.js100.00%100.00%70.00%
   TemplateDocsLink.js100.00%100.00%100.00%
   TemplateFooterActions.js100.00%100.00%100.00%
   TemplateHeaderNavigation.js82.35%85.71%70.00%
   TemplateHeaderTitle.js100.00%100.00%100.00%
   TemplateList.js100.00%100.00%100.00%
   TemplateListItem.js100.00%100.00%92.86%
   TemplateListItemComponents.js100.00%100.00%100.00%
   TemplateManagerClosed.js100.00%100.00%100.00%
   TemplateScreenshot.js100.00%100.00%100.00%
   TemplateScreenshots.js100.00%100.00%50.00%
   TemplateSearch.js93.75%88.89%50.00%
   TemplateSingle.js100.00%100.00%100.00%
   TemplateSingleComponents.js100.00%100.00%75.00%
   TemplateUploader.js100.00%100.00%95.00%
   TemplateUploaderContext.js100.00%100.00%100.00%
   TemplateUploaderTile.js100.00%100.00%100.00%
src/assets/js/react/reducers
   fontManagerReducer.js91.46%100.00%81.08%
   index.js100.00%100.00%100.00%
   templateReducer.js100.00%100.00%100.00%
src/assets/js/react/sagas
   fontManager.js90.16%92.86%88.57%
   index.js100.00%100.00%100.00%
   templates.js91.30%100.00%100.00%
src/assets/js/react/selectors
   getTemplates.js91.11%100.00%83.33%
src/assets/js/react/utilities/FontManager
   associatedFontManagerSelectBox.js94.44%100.00%77.78%
   fontManagerReducer.js100.00%100.00%94.12%
   toggleUpdateFont.js100.00%100.00%100.00%
src/assets/js/react/utilities/Template
   hasPendingUpload.js100.00%100.00%100.00%
src/assets/js/react/utilities
   withRouterHooks.js100.00%100.00%100.00%

🤖 Jest coverage report

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Coverage report for commit: 50ee553
File: tmp/coverage/report-xml/merged.xml

Cover ┌─────────────────────────┐ Freq.
   0% │ ██████░░░░░░░░░░░░░░░░░ │  7.1%
  10% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  20% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.4%
  30% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.9%
  40% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.4%
  50% │ ███████░░░░░░░░░░░░░░░░ │  9.3%
  60% │ █░░░░░░░░░░░░░░░░░░░░░░ │  1.3%
  70% │ ██░░░░░░░░░░░░░░░░░░░░░ │  2.7%
  80% │ ████████████░░░░░░░░░░░ │ 16.4%
  90% │ ███████████████████████ │ 31.6%
 100% │ ██████████████████████░ │ 29.8%
      └─────────────────────────┘
 *Legend:* █ = Current Distribution 
Summary - Lines: 90.24% | Methods: 95.88%
FilesLinesMethodsBranches
/var/www/html/wp-content/plugins/gravity-pdf
   api.php98.14%100.00%100.00%
   gravity-pdf-updater.php53.97%100.00%100.00%
   pdf.php59.82%81.25%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Controller
   Controller_Actions.php100.00%100.00%100.00%
   Controller_Activation.php95.83%100.00%100.00%
   Controller_Custom_Fonts.php95.52%100.00%100.00%
   Controller_Debug.php100.00%100.00%100.00%
   Controller_Export_Entries.php96.77%100.00%100.00%
   Controller_Font_Downloader.php100.00%100.00%100.00%
   Controller_Font_Sources.php100.00%100.00%100.00%
   Controller_Form_Settings.php87.37%90.00%100.00%
   Controller_Install.php100.00%100.00%100.00%
   Controller_Mergetags.php100.00%100.00%100.00%
   Controller_PDF.php81.46%100.00%100.00%
   Controller_Pdf_Cache.php100.00%100.00%100.00%
   Controller_Pdf_Queue.php85.27%87.50%100.00%
   Controller_Save_Core_Fonts.php91.67%100.00%100.00%
   Controller_Settings.php86.90%100.00%100.00%
   Controller_Shortcodes.php100.00%100.00%100.00%
   Controller_System_Report.php100.00%100.00%100.00%
   Controller_Templates.php100.00%100.00%100.00%
   Controller_Uninstaller.php83.33%77.78%100.00%
   Controller_Upgrade_Routines.php95.19%100.00%100.00%
   Controller_Webhooks.php100.00%100.00%100.00%
   Controller_Zapier.php100.00%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Exceptions
   GravityPdfDatabaseUpdateException.php50.00%100.00%100.00%
   GravityPdfDomainException.php50.00%100.00%100.00%
   GravityPdfException.php50.00%100.00%100.00%
   GravityPdfFontNotFoundException.php50.00%100.00%100.00%
   GravityPdfIdException.php50.00%100.00%100.00%
   GravityPdfModelNotUpdatedException.php50.00%100.00%100.00%
   GravityPdfNotATemplateException.php50.00%100.00%100.00%
   GravityPdfRuntimeException.php50.00%100.00%100.00%
   GravityPdfShortcodeEntryIdException.php50.00%100.00%100.00%
   GravityPdfShortcodePdfConditionalLogicFailedException.php50.00%100.00%100.00%
   GravityPdfShortcodePdfConfigNotFoundException.php50.00%100.00%100.00%
   GravityPdfShortcodePdfInactiveException.php50.00%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Fields
   Field_Address.php92.86%100.00%100.00%
   Field_Chainedselect.php66.67%75.00%100.00%
   Field_Checkbox.php94.44%100.00%100.00%
   Field_Consent.php95.00%100.00%100.00%
   Field_Coupon.php--100.00%
   Field_Creditcard.php83.33%100.00%100.00%
   Field_Date.php83.33%100.00%100.00%
   Field_Default.php83.33%100.00%100.00%
   Field_Discount.php44.00%75.00%100.00%
   Field_Email.php83.33%100.00%100.00%
   Field_Fg_Ls_Consent.php92.86%100.00%100.00%
   Field_Fg_Ls_Signature.php73.08%66.67%100.00%
   Field_Fileupload.php95.83%100.00%100.00%
   Field_Form.php90.91%100.00%100.00%
   Field_Hidden.php81.82%100.00%100.00%
   Field_Html.php89.47%100.00%100.00%
   Field_Image_Choice.php86.67%100.00%100.00%
   Field_Likert.php97.22%100.00%100.00%
   Field_List.php92.41%100.00%100.00%
   Field_Multi_Choice.php50.00%100.00%100.00%
   Field_Multiselect.php92.59%100.00%100.00%
   Field_Name.php84.62%100.00%100.00%
   Field_Number.php83.33%100.00%100.00%
   Field_Option.php96.15%100.00%100.00%
   Field_Page.php83.33%100.00%100.00%
   Field_Phone.php94.55%100.00%100.00%
   Field_Poll.php93.75%100.00%100.00%
   Field_Post_Category.php85.00%100.00%100.00%
   Field_Post_Content.php82.35%100.00%100.00%
   Field_Post_Custom_Field.php50.00%100.00%100.00%
   Field_Post_Excerpt.php81.82%100.00%100.00%
   Field_Post_Image.php94.00%100.00%100.00%
   Field_Post_Tags.php90.91%100.00%100.00%
   Field_Post_Title.php81.82%100.00%100.00%
   Field_Product.php92.31%100.00%100.00%
   Field_Products.php84.32%100.00%100.00%
   Field_Quantity.php84.62%100.00%100.00%
   Field_Quiz.php89.74%100.00%100.00%
   Field_Radio.php94.74%100.00%100.00%
   Field_Rank.php95.24%100.00%100.00%
   Field_Rating.php95.24%100.00%100.00%
   Field_Repeater.php97.39%100.00%100.00%
   Field_Section.php90.74%100.00%100.00%
   Field_Select.php94.12%100.00%100.00%
   Field_Shipping.php92.86%100.00%100.00%
   Field_Signature.php71.11%100.00%100.00%
   Field_Slim.php82.35%100.00%100.00%
   Field_Slim_Post.php91.30%100.00%100.00%
   Field_Subtotal.php65.38%75.00%100.00%
   Field_Survey.php95.00%100.00%100.00%
   Field_Tax.php32.00%50.00%100.00%
   Field_Text.php81.82%100.00%100.00%
   Field_Textarea.php91.18%100.00%100.00%
   Field_Time.php81.82%100.00%100.00%
   Field_Tos.php92.86%100.00%100.00%
   Field_Total.php88.00%100.00%100.00%
   Field_Website.php85.71%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Fonts
   FlushCache.php92.31%100.00%100.00%
   LocalFile.php88.89%100.00%100.00%
   LocalFilesystem.php66.67%100.00%100.00%
   SupportsOtl.php87.50%100.00%100.00%
   TtfFontValidation.php84.62%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper
   Helper_Abstract_Addon.php94.09%100.00%100.00%
   Helper_Abstract_Config_Settings.php75.00%100.00%100.00%
   Helper_Abstract_Controller.php-100.00%100.00%
   Helper_Abstract_Field_Products.php89.47%66.67%100.00%
   Helper_Abstract_Fields.php96.10%95.83%100.00%
   Helper_Abstract_Fields_Input_Type.php84.00%100.00%100.00%
   Helper_Abstract_Form.php--100.00%
   Helper_Abstract_Model.php100.00%100.00%100.00%
   Helper_Abstract_Options.php77.33%81.36%100.00%
   Helper_Abstract_Pdf_Shortcode.php94.67%95.65%100.00%
   Helper_Abstract_View.php96.77%100.00%100.00%
   Helper_Async_Notifications.php64.29%100.00%100.00%
   Helper_Data.php98.43%100.00%100.00%
   Helper_Field_Container.php92.31%100.00%100.00%
   Helper_Field_Container_Gf25.php92.00%100.00%100.00%
   Helper_Field_Container_Void.php16.67%-100.00%
   Helper_Form.php80.65%64.29%100.00%
   Helper_Interface_Actions.php-100.00%100.00%
   Helper_Interface_Config.php50.00%100.00%100.00%
   Helper_Interface_Config_Settings.php50.00%100.00%100.00%
   Helper_Interface_Deprecated_Features.php50.00%100.00%100.00%
   Helper_Interface_Extension_Settings.php-100.00%100.00%
   Helper_Interface_Extension_Uninstaller.php-100.00%100.00%
   Helper_Interface_Field_Pdf_Config.php50.00%100.00%100.00%
   Helper_Interface_Filters.php-100.00%100.00%
   Helper_Interface_Setup_TearDown.php50.00%100.00%100.00%
   Helper_Interface_Url_Signer.php-100.00%100.00%
   Helper_Logger.php-100.00%100.00%
   Helper_Misc.php89.17%100.00%100.00%
   Helper_Mpdf.php50.00%100.00%100.00%
   Helper_Notices.php92.98%100.00%100.00%
   Helper_Options_Fields.php98.10%100.00%100.00%
   Helper_PDF.php88.61%97.56%100.00%
   Helper_PDF_List_Table.php84.50%92.31%100.00%
   Helper_Pdf_Queue.php84.31%100.00%100.00%
   Helper_QueryPath.php80.00%100.00%100.00%
   Helper_Render_Health.php85.71%100.00%100.00%
   Helper_Sha256_Url_Signer.php90.91%100.00%100.00%
   Helper_Singleton.php100.00%100.00%100.00%
   Helper_Templates.php97.29%100.00%100.00%
   Helper_Trait_Logger.php25.00%-100.00%
   Helper_Trait_Removed_Methods.php100.00%100.00%100.00%
   Helper_Url_Signer.php84.82%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Licensing
Table truncated to fit comment

🤖 PHPUnit coverage report

@gravitypdf-bot
gravitypdf-bot force-pushed the feature/font-health-reporting branch from 3adbb21 to a631b60 Compare November 6, 2026 00:34
@gravitypdf-bot
gravitypdf-bot changed the base branch from feature/core-font-upgrade-prune to feature/font-file-conflict-rename November 6, 2026 00:35
@gravitypdf-bot
gravitypdf-bot force-pushed the feature/font-health-reporting branch from a631b60 to 1dd5d2c Compare November 6, 2026 01:56
@jakejackson1
jakejackson1 force-pushed the feature/font-file-conflict-rename branch from f7acf3e to 74c3b06 Compare November 6, 2026 03:06
@gravitypdf-bot
gravitypdf-bot force-pushed the feature/font-file-conflict-rename branch from 74c3b06 to 1ad0a3c Compare November 9, 2026 05:30
@gravitypdf-bot
gravitypdf-bot force-pushed the feature/font-file-conflict-rename branch 2 times, most recently from 62cbe50 to 38e02af Compare November 9, 2026 06:09
Base automatically changed from feature/font-file-conflict-rename to development November 9, 2026 06:12
@gravitypdf-bot
gravitypdf-bot force-pushed the feature/font-health-reporting branch 7 times, most recently from 5409f02 to 77d1bef Compare November 10, 2026 04:13
@gravitypdf-bot gravitypdf-bot added update-visual-baselines Refresh Lost Pixel visual baselines from this PR's run (pair with run-tests) and removed update-visual-baselines Refresh Lost Pixel visual baselines from this PR's run (pair with run-tests) labels Nov 10, 2026
A font that gave up after its retry showed only in the admin notice, which can be dismissed for good, and a site with
downloads turned off read as broken in the System Report ("0 of 4 required files installed").

The System Report gains two rows. "Core Fonts failed" lists the files that gave up, whatever the notice's dismissals
say. "Core Font downloads" reads the constant, then asks the filter about every manifest file, so it doesn't depend on
what happens to be missing.

A give-up is forgotten once its file is on disk, so the admin notice and the "Core Fonts failed" row don't go on listing
a font copied in by hand. Downloads and retries already cleared the record, but give-ups are skipped by the sync.

The Site Health test gravity_pdf_core_fonts is critical when a missing required file gave up, as someone has to act and
PDFs can lose text to the fallback font, and recommended when downloads were only turned off, which was a choice. It
names the files and the cause, and clears itself once the fonts are on disk. A file counts as present by Model_Font_Sources::is_installed(), the same check as the installed
counts, so one another font's file holds the name of is missing until its hashed copy is saved.

Direct Site Health tests block the page, so the form scan behind the missing files only runs when a file has given up
or the constant or filter could block a download.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gravitypdf-bot
gravitypdf-bot force-pushed the feature/font-health-reporting branch from 14c082f to 50ee553 Compare November 10, 2026 04:19
@jakejackson1
jakejackson1 merged commit c52cd6b into development Nov 10, 2026
@jakejackson1
jakejackson1 deleted the feature/font-health-reporting branch November 10, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants