Skip to content

[3.0] Adds a repeatable converter from template functions to Plates templates (part 1 of 2) - #9727

Open
albertlast wants to merge 10 commits into
SimpleMachines:release-3.0from
albertlast:3.0/plates-converter
Open

albertlast wants to merge 10 commits into
SimpleMachines:release-3.0from
albertlast:3.0/plates-converter

Conversation

@albertlast

@albertlast albertlast commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Description

This adds the tooling that converts the default theme's templates to Plates, and the tooling that proves a conversion changed nothing on the page. Part 2 (#9728) is the conversion itself, and every file under Themes/default/templates/ in part 2 comes out of this converter. Nothing here changes the forum; it is all under .dev/.

This is stacked on #9712 (template snapshot tests), which the comparison depends on. Until that merges, this PR's diff includes #9712's commits. The two commits that belong to this PR are the last ones: SnapshotTestCase can save each page's HTML, and the converter itself.

Converting
.dev/convert-templates.sh --from <commit> --all --skip Stats
  • .dev/plates/convert.php works on PHP tokens, not with regular expressions. It turns each template_*() function into its own Plates file, laid out so the file outputs exactly the same bytes as the function did.
  • Calls between templates become $this->subTemplate('name', [...]), with parameter names taken from the called function's signature. A converted template can therefore call a sub-template of either kind.
  • It stops on anything it can't convert faithfully. It warns about anything a person should check: a template that returns a value, a parameter passed by reference, or a call whose parameters it can't find.
  • The script starts from the old files as a given commit has them, so it can be repeated as often as needed with the same result.
  • After converting, it applies three fix-ups the default theme needs, drops the empty lines the conversion leaves where HTML doesn't need them, and runs php-cs-fixer.
Checking
.dev/capture-pages.sh before
# change the templates
.dev/capture-pages.sh after
.dev/compare-pages.sh before after [--rendered] -v
  • capture-pages.sh saves the HTML of all 232 pages the snapshot suite renders, on both engines. It also saves ssi_examples.php, some XML responses, and a probe that calls the template helpers directly, as a mod would.
  • compare-pages.sh first masks what changes between any two runs: sessions, tokens, times and counts. By default, everything else must match byte for byte.
  • With --rendered, runs of whitespace count as one space, as a browser shows them. Inside <pre>, <textarea> and <script>, where a newline matters, the bytes must still match exactly.

The snapshot suite in #9712 compares a description of each page's DOM, which ignores whitespace, attribute order and the forum's own data. That is right for catching a broken page, but too coarse to prove a conversion changed nothing. This byte-level check is what makes it reasonable to review a conversion of 54 templates by reviewing the converter rather than 342 generated files.

Verified
  • On a clean checkout, .dev/convert-templates.sh --from ea5ae213e --all --skip Stats reproduces every file part 2 has under Themes/default/templates/. Stats is the exception: it was converted by hand, as the first test of the engine, before the converter existed.
  • The capture and comparison were run on both engines. Straight out of the converter, 460 of the 464 pages were byte-identical to the old templates. The other four were the theme copy page, which part 2 changes on purpose, and ties in PostgreSQL's ordering ([3.0] Lists the forum administrators in a defined order #9721, [3.0] Ranks ties in the stats top tens in a defined order #9722).
  • Two things the comparison caught during the conversion:
    • Literal '<', '?xml' pieces that, joined together, would have opened a PHP tag in every XML response. No snapshot page is an XML response; the extra captures found it.
    • A first version of the tidying step that removed newlines inside <script>.

Issues References (Fixes|Related|Closes)

Related: #9712 (this PR's base); #9728 (part 2 of 2, the conversion to Plates).

🤖 Generated with Claude Code

albertlast and others added 10 commits October 5, 2026 06:41
Records what about 230 pages render today, as a guest, a member and an
administrator, so that moving the templates to Plates can be checked page
by page. A page that renders differently fails, and the diff says how.

Pages are compared as DomSnapshot describes them rather than as HTML:
whitespace, comments and attribute order are dropped, and the forum's
own data - ids, counts, dates, names, sessions, list lengths - is
masked. Pages that list content look at fixtures built once per forum,
and lists of the whole forum are narrowed to them, so the snapshots do
not change when somebody posts, registers or adds a board. The errors a
page logs are part of its snapshot.

perturb-forum.php fills a throwaway forum with unrelated members, boards
and posts. Recorded on a fresh MySQL forum, the snapshots pass there and
on a fresh PostgreSQL forum, and on both again after two rounds of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
…d-in forum showed

HttpTestCase slept for three seconds and retried whenever flood control
turned a login or a post away. As suggested in review, submitForm() now
deletes the rows in log_floodcontrol first, so there is nothing to wait
out and no test depends on how quickly it runs. The retry logic goes.

Running the snapshots against a forum that had been used, rather than a
new one, found content they still depended on:

- the forum administrator's own profile, since the fixtures posted as
  them; a fixture administrator posts instead, and the fixtures carry a
  version so that forums holding the old ones rebuild them
- the hash in a minified file's name, which \b never matched after "_"
- ;boardseen, decimals and thousands in numbers, email addresses, the
  encoded parameters of a search, and fixture ids in the selectors
- the errors a member had logged, on their tracking page

The recording itself had two faults: a Settings_bak.php the forum could
not write, which put a warning on every settings page, and the password
prompt in front of a member's account settings, which was recorded in
place of the page. The suite now gets past the prompt for members as it
already did for the administrator.

Snapshot tests also reuse their signed in browser rather than making a
new one per test, which cost a request each and a third of the run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
docker compose exec starts a fresh environment, so test.sh only hands over
the variables it names. SMF_UPDATE_SNAPSHOTS was not one of them, and under
the docker runner the documented way to re-record the snapshots compared
against them instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
The search results snapshots open search2 from a link, and SMF turns away a
search made within a few seconds of the last one. With each request taking
about a second, as it does over a Windows bind mount, the two search pages
were never close enough together to notice. On a Linux filesystem the suite
runs about twenty times faster, and the second search came back as a 403.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
profile_track_ip pinned a fatal that SimpleMachines#9718 has fixed, so it now records the
page. features_basic and profile_theme show the time zone select grouped by
country. themes_copy lists the new TimeZoneSelect template and no longer
logs an array to string conversion, which SimpleMachines#9720 fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
Adds the license header to any test file this adds, and writes the
docblock of each new test method in the agreed shape: Expected:, Guards:
for a regression, and @link lines for the commit that introduced the bug
and for this pull request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
HttpTestCase now shares one guest browser between tests, and
signInAsAdmin() signs in a browser of its own. The snapshot classes
need a browser per audience, so their first browser is a new one rather
than the shared guest, which the member audience would otherwise sign
in for every test after it. The admin audience signs in a fresh browser
rather than the shared one, since passing the admin security check
changes its session, and the audience's browser is kept once signing in
is done.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
The time zone pickers on the basic features page and the theme profile
page name and order each zone by whether daylight saving is in effect
that day, so both snapshots failed when Australia moved its clocks on
4 October, with no template involved. Both cases now ignore the select,
which the snapshot still records as being there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
With SMF_SNAPSHOT_RAW set, every page the suite compares is also saved as it
was sent, one directory per engine. The snapshots leave whitespace out on
purpose; comparing two of these captures after masking sessions, tokens and
numbers shows whether a converted template renders byte for byte what the
old one did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
.dev/convert-templates.sh converts the default theme's *.template.php files
into one Plates file per sub-template, starting again from the old files as a
commit has them on every run. .dev/capture-pages.sh saves every page the
snapshot suite renders, on both engines, plus SSI, XML responses and a probe
calling the template helpers the way a mod does; .dev/compare-pages.sh diffs
two captures byte for byte, or as a browser renders them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
@albertlast
albertlast force-pushed the 3.0/plates-converter branch from 7c13423 to 0b4782f Compare October 5, 2026 04:49
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.

1 participant