Skip to content

Text Transforms Developer Guide

Ed Mozley edited this page Nov 13, 2026 · 1 revision

Text transforms in placeholders β€” Developer Guide

5.2.0 Β· #317 (from discussion #298, by Shadowtech87) Β· User guide: Starters and leavers Β§ Questions Β· Module guide: Starters and leavers - Developer Guide

πŸ”‘ The one-line version

{First name|initial|upper} - a placeholder can now work a value out on its way into text, not just copy it. One shared file, includes/text_transforms.php, does it. Starters & leavers step text is the first place it is used. Forms' actions and workflow variables can use the same function later.

Why

A starter's steps need values worked out from the form's answers: a PC name ORG-JSMITH, a username jsmith, an email address john.smith@example.org. Before this, the analyst worked them out by hand, and two people worked them out two ways. Shadowtech87's previous tool did it for them.

πŸ“ Files

File What
includes/text_transforms.php TEXT_TRANSFORMS, textTransform(), textToAscii(), textFillPlaceholders()
includes/starters/service.php StartersService::fillAnswers() builds the name => value map and calls textFillPlaceholders()
assets/js/starters-settings.js (v=6) A one-line hint under the {Question} buttons in the template editor (settings.chips_hint)
lang/en/starters.php, starters/help.php The hint, and help paragraph help.questions.p5 (the section now has 5 paragraphs)
tests/text-transforms.php 26 checks, needs no database

🧰 The transforms

Applied left to right. Names are case- and space-insensitive.

Name Does John Paul β†’
initial the first letter (multi-byte safe: Γ‰mile β†’ Γ‰) J
first the first word John
last the last word Paul
upper / lower capitals / small letters JOHN PAUL / john paul
nospace spaces taken out JohnPaul
slug lower case, accents folded, every run of anything not a-z / 0-9 becomes . john.paul
ascii letters folded to plain A-Z: JosΓ© β†’ Jose, Łukasz β†’ Lukasz John Paul
function textTransform(string $value, array $names): ?string   // null = a name is not a transform
function textFillPlaceholders(string $text, array $map): string  // $map: lower-case name => value

textFillPlaceholders('ORG-{First name|initial|upper}{Last name|upper|nospace}',
                     ['first name' => 'John', 'last name' => 'Smith']);   // "ORG-JSMITH"

textToAscii() uses ICU's Transliterator('Any-Latin; Latin-ASCII') when the intl extension is there. Unlike stripping accent marks, that also folds letters such as Ł and ø. Without intl it falls back to Normalizer (decompose, then drop the marks), and without that it leaves the value as it is.

⚠️ Rules that matter

  • πŸ”‘ A typo is never silent. An unknown transform makes textTransform() answer null, and the whole placeholder is left exactly as typed (ORG-{Last name|uper}). An unknown question is left as typed too, as it always was. Someone reading the step sees the mistake. They never get a quietly wrong PC name.
  • A short, plain-word list - not a formula language. Adding substr(2,3) or if here turns step text into code nobody can read. A new transform needs a real need, a plain name, a row in the table above, and a test.
  • Placeholders are matched case-insensitively by the question's wording ($map keys are lower case), as before. That is why a new version of a form keeps working.

πŸ§ͺ Tests

  • tests/text-transforms.php (26, no database):
    • every transform, with a multi-byte initial, ascii folding Ł, and names given in any case;
    • an unknown transform giving null;
    • the issue's three examples (ORG-JSMITH, jsmith, john.smith@example.org);
    • a misspelt transform, and an unknown question, left as typed;
    • an empty answer;
    • two checks through StartersService::fillAnswers().
  • tests/starters.php (46, prtest) still passes. It fills {Question} in real step text.

See also: Starters and leavers - Developer Guide Β· Starters steps as tickets - design (#316, whose ticket steps will use the same transforms)

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Responses to feedback

Blue sky thinking

Bugs resolved

Pull requests

Links

Clone this wiki locally