Repository navigation
List custom, core and bundled fonts together in the Font Manager - #2015
Merged
Merged
Conversation
Contributor
|
Coverage report for commit: 37b7e8c Summary - Lines: 93.99% | Methods: 90.96% | Branches: 85.66%
🤖 Jest coverage report |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Contributor
|
Coverage report for commit: 37b7e8c Summary - Lines: 89.51% | Methods: 95.69%
🤖 PHPUnit coverage report |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
gravitypdf-bot
force-pushed
the
feature/font-manager-downloaded-fonts
branch
2 times, most recently
from
November 5, 2026 22:51
f5c9ccc to
771fac4
Compare
Merged
10 tasks done
Base automatically changed from
feature/core-font-upgrade-prune
to
development
November 6, 2026 03:06
jakejackson1
force-pushed
the
feature/font-manager-downloaded-fonts
branch
from
November 6, 2026 03:06
771fac4 to
52fdbd8
Compare
jakejackson1
reviewed
Nov 6, 2026
| * @since 6.19.0 | ||
| */ | ||
| public function can_view_fonts(): bool { | ||
| $allowed = GPDFAPI::get_form_class()->has_capability( 'gravityforms_edit_forms' ); |
Member
There was a problem hiding this comment.
should match the pdf editing permissions.
jakejackson1
reviewed
Nov 6, 2026
Member
|
Should replace with @wordpress/components? Or leave until 7.0? |
gravitypdf-bot
force-pushed
the
feature/font-manager-downloaded-fonts
branch
3 times, most recently
from
November 8, 2026 23:07
0d77c74 to
9b74d46
Compare
gravitypdf-bot
force-pushed
the
feature/font-manager-downloaded-fonts
branch
7 times, most recently
from
November 9, 2026 00:57
0321f1b to
2e608c0
Compare
gravitypdf-bot
force-pushed
the
feature/font-manager-downloaded-fonts
branch
from
November 9, 2026 02:16
2e608c0 to
edf2097
Compare
On-demand downloading makes deleting a core font safe, as one a PDF needs comes back on its own, but the Font Manager
only listed custom fonts, so a downloaded font could only be removed by hand from the fonts folder.
There is now one list that the search box filters: custom fonts, downloadable fonts with files on disk and listed
bundled fonts. Following the 7.0 Font Manager design for what 6.19 can already do, fonts sit in a sidebar with the
selected font first and Custom, Bundled and Core groups below it. Clicking a font opens its detail: bundled and core
fonts are read-only, custom fonts open the update form. Each shows its styles, size, what's using it and a live preview,
and links to the settings of the PDFs using it. Uploads are rows rather than tiles, deleting asks in a dialog, and the
actions sit in a bar pinned to the bottom of the pane.
A preview is a whole TTF per style, so it waits until it has been on screen for a moment, as moving to another font
doesn't cancel a download, and shows one style until another is picked from its dropdown. Anything over 4 MB, such as
Sun-ExtA at 22 MB, waits for a click on Load preview, using the per-style file_sizes now on each row. Text uses
font-display: swap rather than staying blank while the files load, with a spinner beside each style until its file has, or a note if it couldn't load. Sun-ExtA isn't offered a preview, as
its vhea table claims more metrics than it has glyphs and browsers reject the file.
A fonts folder moved with gfpdf_font_location has its
path mapped to a URL, and the preview says it's unavailable when there isn't one.
The route now decides which panel shows, rather than a class toggled on the DOM, so browser Back no longer leaves the
update form open. That removes the slide-in panel's height and tab index workarounds.
GET /fonts/?scope=all returns every row and GET /fonts/ stays custom-only by default so existing consumers keep working. Working out
what's in use walks every form, and on Multisite every site, so GET /fonts/?scope=usage serves `reasons`, `pdfs_label`
and `pdfs` separately: rows appear at once and Delete enables when the reasons arrive. Saved custom fonts return the same
row as the list.
A font in use can't be deleted, custom fonts included: DELETE /fonts/{id} now returns 409 for one, though not
GPDFAPI::delete_pdf_font(), which the upgrade uses to remove records a font source now serves. DELETE
/fonts/{id}?scope=core returns 409 when in use and 404 for a bundled, unknown or absent family. It removes the family's
manifest files whatever their hash (an explicit action, unlike the upgrade prune), keeps the licence files, clears the
files' failure and back-off entries, flushes the family's metrics and logs what it removed. With downloads turned off
the confirm says the font won't come back.
Core fonts follow the order of the font dropdown. Those with nothing on disk are listed as available to install, unless downloads are off or they have no label, so
can't be chosen for a PDF. POST /fonts/{id}?scope=core downloads a family's missing files whatever their back-off, and
returns its row. On Multisite only super admins can, as with delete. Deleting returns the row too, so a font that can be
installed again goes back to the available group. With nothing on the site to preview, an available font's preview loads
from its manifest URL. Core rows also carry the languages and scripts each font supports, worked out from the characters
in its file, and a sample in its own script for fonts whose Latin letters wouldn't show what they're for.
The in-use reasons come from Model_Required_Fonts::get_font_reasons(), which get_required_font_files() is now built on,
so the list and the background sync share one walk of the forms, which now pages by ID as OFFSET ran its LIKE over every
form it skipped. On Multisite the fonts folder is shared, so only super admins can delete core fonts, and "in use" also
counts every other site's default font, locale font and PDF fonts, though a site's custom fonts are its own. Those come
from Model_Required_Fonts::get_site_font_keys(), which reads a site's tables by prefix rather than switch_to_blog() so no
other site's plugins or filters run. One options query per site also says whether Gravity Forms has run there
(gf_db_version), so no site pays a separate table check. Only super admins walk the other sites for the usage list, as
only they can delete core fonts. The form scan's LIKE compares bytes, as the column's collation made it about 6x slower.
The delete check stops at the first thing using the font, so the form reads are generators.
All of this is on the existing /fonts/ and /fonts/{id} routes, so there are no new endpoints to maintain.
The E2E test copies a core font no other spec uses into the fonts folder, as downloads are off on the E2E site, and puts
one in use with an X-GPDF-E2E-Default-Font header rather than a PDF selecting it, which would count it as required in the
other specs' system reports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gravitypdf-bot
force-pushed
the
feature/font-manager-downloaded-fonts
branch
from
November 9, 2026 02:40
edf2097 to
37b7e8c
Compare
This was referenced Nov 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Font Manager now holds custom, downloaded core and bundled fonts together in one sidebar, with a detail pane for each font, following the 7.0 design for what 6.19 can already do. Until now a downloaded core font could only be removed by hand from the fonts folder, and nothing showed which PDFs used a font.
scopeargument on the existing/gravity-pdf/v1/fonts/and/fonts/{id}routes does the new work. It defaults tocustom, so existing consumers see no change.GET /fonts/?scope=allreturns every row: custom and listed bundled fonts by name, then core fonts in the font dropdown's order.GET /fonts/?scope=usagereturns why fonts are in use and which PDFs use them. It walks the forms, so rows appear first and Delete enables when it returns.POST /fonts/{id}?scope=coreinstalls a core font's missing files and returns its row. It returns 404 for a bundled, unknown or custom-replaced family, 409 with downloads off and 502 when a download fails.DELETE /fonts/{id}?scope=coreremoves a core font's files and keeps its licence files. It returns 409 when in use and 404 for a bundled, unknown or absent family.DELETE /gravity-pdf/v1/fonts/{id}now returns 409 for a custom font in use. This is a behaviour change for anything calling the route.GPDFAPI::delete_pdf_font()is unchanged, as the upgrade uses it to remove records a font source now serves.raw.githubusercontent.com.Try it
wp cron event run gfpdf_core_font_sync. Open the Font Manager from the PDF's Font setting: Free Serif is at the top, tagged Active and saying "In use"..ttfonto a row and add the font.define( 'GPDF_AUTO_INSTALL_FONTS', false );, then open an unused core font. Its description and delete dialog warn that it won't come back on its own.Test plan
test_an_unwritable_folder_fails_without_a_requestcases fail locally only, and passed in CI on the previous commitcore/managers/font-manager.spec.tspasses (18 tests,coreproject)core-with-permalinksin CISkipped
Performance on large sites (tracked in #2018)
Known limitations
gfpdf_font_locationpreviews when its path maps to a URL, and says it's unavailable when it doesn't. A folder that maps to a URL but blocks web access shows "Couldn't load this style".Clean-up
ShowMessagefor the deleted-font notice, which needs a success style first.Design differences from the mockup
More info
fontUsagesits besidefontListin the store rather than merged into its rows, because changingfontListrepopulates an open update panel and would reset what's being typed.Model_Required_Fonts::get_site_font_keys( $site_id, $unset_default )reads one site's default font, locale font and PDF fonts by table prefix, neverswitch_to_blog(), so no other site's plugins or filters run. Keep font state in one place for every site, and keep every site's fonts in the 6.19 cleanup #2004's 6.19 cleanup calls the same method.Model_Font_Sources::get_listed_families()holds that rule for both.adjustFontListHeight, the tab index plumbing, orphaned strings and the old 961–1200px rules that were breaking the actions bar at those widths.FontDeleteButtonreplaces two copies of the delete logic.formattribute, so Enter in the preview can't save the font. The delete dialog now covers the sidebar for core fonts too.Controller_Custom_Fonts::delete_item(), so expect a conflict there.fontsUrl()addsscopethroughupdateURLParameter().Model_Font_Downloaderinto its own model, andapiGetCustomFontList/GET_CUSTOM_FONT_LISTnow fetch every type, so the names are out of date.X-GPDF-E2E-Default-Fontheader intools/mu-plugins/gravitypdf.php, which applies to that test's requests only.