fix(ui): build the Task Type icon picker from the stylesheet FOG ships - #1344
Merged
Conversation
TaskType::iconlist() built the icon dropdown by parsing
management/other/_variables.scss -- a Font Awesome 4.7.0 variables file that
no stylesheet imported, that nothing regenerated, and whose only reader was
this method. The Font Awesome 7 migration did not touch it.
So the picker offered 786 v4 names, of which 148 no longer exist in the
shipped build. Among them were all seven names schema steps 361-367 had just
repaired in the database -- plus-square-o, hdd-o, arrow-circle-o-down,
arrow-circle-o-up, hourglass-o, flag-o and bookmark-o. Choosing one wrote the
broken state straight back into taskTypes.ttIcon, which is rendered as
`fas fa-<stored name>` and draws nothing. Fixing the data while leaving the
picker able to rewrite it is not a fix.
The list now comes from management/css/font-awesome.min.css -- the same file
the browser loads -- so it cannot describe a different set of icons from the
one that will render. 1,946 names instead of 786.
Brands are excluded. They resolve in the stylesheet but live only in the
Brands font, and FOG renders stored names with `fas`, so an offered brand
draws a tofu box. The stylesheet does not label an icon with its font, but it
is a concatenation and every brand declaration follows the brands
font-family rule, so that rule's offset is the boundary; it is matched on
`Font Awesome <n> Brands` rather than a fixed 7 so a version bump cannot
silently turn the filter off. Regular needs no filter: in Font Awesome Free
every regular icon name also exists in solid.
Two defects fixed on the way, both in the method being rewritten:
- the glyph beside each name never rendered. The old code built ``
with no trailing semicolon and passed it through Initiator::e(), and
htmlspecialchars cannot recognise that as an entity even with
double_encode off -- so every row showed the literal text. It now emits
the character itself.
- the file was opened on a CWD-relative path. It is read from BASEPATH,
like every other file the class layer touches.
Parsed once per request and memoised, so the two calls the Task Type edit
page makes cost one read.
Pinned by a new section 6 in tests/fontawesome7-icon-names.test.php, which
executes the real method rather than reading its source -- a source check
passes on code that opens the right file and parses it wrongly, and parsing
is where the next version bump will break it. Mutation-verified, three
mutants, all killed:
- drop the brands filter -> 609 brand icons offered
- read only the first class of
each rule (drop FA's grouped
alias selectors) -> a grouped alias goes missing
- go back to the entity form -> escaped entity text, no glyph
The first alias mutant SURVIVED the checks as first written, because they
only asked that everything offered is valid, never that everything valid is
offered. The alias check that closes it derives its expectation from the
stylesheet at run time rather than naming icons, so it survives a version
bump.
management/other/_variables.scss is deleted: nothing imports it and nothing
else reads it.
Co-Authored-By: Claude <noreply@anthropic.com>
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.
The bug
TaskType::iconlist()built the Task Type icon dropdown by parsingpackages/web/management/other/_variables.scss— a Font Awesome 4.7.0 variables file that no stylesheet imports, that nothing regenerates, and whose only reader was this method. The Font Awesome 7 migration (#1336) did not touch it.So the picker offered 786 v4 names, of which 148 no longer exist in the shipped build — including all seven names schema steps 361–367 had just repaired in the database:
plus-square-o·hdd-o·arrow-circle-o-down·arrow-circle-o-up·hourglass-o·flag-o·bookmark-oChoosing one writes the broken state straight back into
taskTypes.ttIcon, which is rendered asfas fa-<stored name>and draws nothing. Fixing the data while leaving the picker able to rewrite it is not a fix.The fix
The list now comes from
management/css/font-awesome.min.css— the same file the browser loads — so it cannot describe a different set of icons from the one that will render. 1,946 names instead of 786.Brands are excluded. They resolve in the stylesheet but live only in the Brands font, and FOG renders stored names with
fas, so an offered brand draws a tofu box (which section 1 of the FA7 test already calls out as worse to eyeball than an absent icon). The stylesheet does not label an icon with its font, but it is a concatenation and every brand declaration follows the brandsfont-familyrule, so that rule's offset is the boundary. It is matched onFont Awesome <n> Brandsrather than a fixed7, so a version bump cannot silently turn the filter off. Regular needs no filter: in Font Awesome Free every regular icon name also exists in solid.Parsed once per request and memoised — the two calls the Task Type edit page makes cost one read.
Two more defects fixed on the way
Both in the method being rewritten:
with no trailing semicolon and passed it throughInitiator::e();htmlspecialcharscannot recognise that as an entity even withdouble_encodeoff, so every row showed the literal text. It now emits the character itself.'../management/other/...'). It is read fromBASEPATH, like every other file the class layer touches.Pinned
New section 6 in
tests/fontawesome7-icon-names.test.php. It executes the real method rather than reading its source — a source check passes on code that opens the right file and parses it wrongly, and parsing is where the next version bump will break it._faIcons()depends on nothing butBASEPATHand that file, so the two methods lift into a bare host class with no FOG boot; extraction failing is a hard failure, not a quiet pass.Mutation-verified, three mutants, all killed:
The alias mutant survived the checks as first written, because they only asked that everything offered is valid, never that everything valid is offered. The alias check that closes it derives its expectation from the stylesheet at run time rather than naming icons, so it survives a version bump.
Suite: 145 passed, 0 failed.
management/other/_variables.scssis deleted — nothing imports it and nothing else reads it.🤖 Generated with Claude Code
https://claude.ai/code/session_01XqpPXAk7bEm8huH9WkiGk6