Repository navigation
Description
Follow-up to #2021 / #2035. Only Model_Font_Downloader knows when a file at a core font's name is another font's of a known size, so the rest of the plugin still counts it as the font's own copy. Model_Font_Sources::get_own_copy() and is_installed() only compare sizes.
It needs another font's file at a core font's name with the size of a known build, so it should be rare. A file of a different size isn't affected.
1. Site Health, the System Report and the Font Manager say the font is installed
#2035 makes the failed fonts notice list the font once its retry gives up. These all still go by size, though:
Model_Required_Fonts::get_missing_files()doesn't count the file as missing.Model_System_Report::get_core_font_health()only keeps failures for missing files, so Site Health drops the failure while the notice shows it.get_installed_counts()(System Report) counts the font as installed.needs_download()(Font Manager rows, andController_Font_Downloader, which skipsschedule_sync()because of it) says the font needs no download.
Impact: the notice says the font failed, while Site Health, the System Report and the Font Manager say it's installed.
2. Deleting the family can delete the other font's file
Model_Font_Downloader::get_core_families() builds each family's paths from get_own_copy(), so the other font's file at the name counts as the family's copy. delete_downloaded_font() then deletes it when the family is unused. The only exception is when another site's custom font uses that name.
This applies until the sync saves the real font under its hashed name, and for as long as that download keeps failing. The method's docblock says it keeps "any other font's file at a family file's name".
Impact: a user's font file can be deleted from the fonts folder. A Font Manager record keeps the file it uses, so this hits loose files, for example ones a template loads by name.
To decide
Model_Font_Downloader::has_own_copy() from #2035 knows about a file a failed download found, but it isn't conclusive before the sync's first verified pass. Options:
- Route these callers through the downloader's check:
Model_Required_Fontswould need the downloader, andget_core_families()would use it forpaths. This fixes the mismatch, but Improve admin.js #2 still has a gap before the first sync. - Before deleting, hash a plain-name file that has no hashed copy, as the sync does. Deletes are rare and run off the render path, so the cost is fine there, and it closes Improve admin.js #2 completely.
- Do both: the downloader's check for reporting, and a hash before deleting.
Activity
Keep another font's file when deleting a core font
Count a font whose download hit another font's file as missing
Keep another font's file when deleting a core font
Count a font whose download hit another font's file as missing
Keep another font's file when deleting a core font
Count a font whose download hit another font's file as missing
Count a font whose download hit another font's file as missing