Add FormatterModifier to unify placeholder modifiers#12
Conversation
524a933 to
cd9ecd2
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #12 +/- ##
============================================
+ Coverage 99.45% 99.47% +0.01%
- Complexity 155 163 +8
============================================
Files 23 24 +1
Lines 368 382 +14
============================================
+ Hits 366 380 +14
Misses 2 2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
cd9ecd2 to
68e195d
Compare
68e195d to
892f25b
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces FormatterModifier, enabling any existing formatter (e.g. date, number, mask, pattern, metric) to be used directly in PlaceholderFormatter pipe syntax, reducing the need for formatter-specific modifier classes. It also updates placeholder parsing to better support backslash-escaped characters in modifier arguments and expands docs/tests accordingly.
Changes:
- Add
FormatterModifierand prepend it toPlaceholderFormatter’s default modifier chain. - Update placeholder parsing regex to support backslash-escaped sequences within the pipe segment.
- Add unit/integration tests and documentation for using formatters as modifiers (including escaped
:/|in arguments).
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/PlaceholderFormatter.php |
Prepends FormatterModifier to the default modifier chain; updates placeholder regex for escaped sequences. |
src/Modifiers/FormatterModifier.php |
New modifier that resolves formatters dynamically via FormatterBuilder and applies them based on pipe syntax. |
tests/Unit/PlaceholderFormatterTest.php |
Adds coverage for escaped : and ` |
tests/Unit/Modifiers/FormatterModifierTest.php |
Adds unit tests for formatter resolution/delegation behavior. |
tests/Integration/PlaceholderFormatterWithFormattersTest.php |
Adds integration tests demonstrating formatters used as modifiers in templates. |
docs/modifiers/Modifiers.md |
Adds FormatterModifier to the list of available modifiers. |
docs/modifiers/FormatterModifier.md |
New documentation describing syntax, escaping, and behavior of FormatterModifier. |
docs/PlaceholderFormatter.md |
Updates docs to show formatter-as-modifier usage and links to FormatterModifier docs. |
README.md |
Adds a quick-start example for using formatters as modifiers. |
composer.lock |
Adds lockfile to the repository. |
Comments suppressed due to low confidence (1)
docs/modifiers/FormatterModifier.md:176
- The “Value Conversion” and “Error Handling” sections describe delegating to the next modifier to stringify non-strings and delegating when a formatter throws during formatting. The current implementation casts scalar values to string directly and does not catch exceptions from
format(). Please align the documentation with the actual behavior, or update the implementation to match the documented delegation behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Introduce a generic FormatterModifier that dynamically instantiates and
applies any formatter based on the pipe syntax. This eliminates the need
to create separate modifier classes for each formatter.
The modifier parses `{{placeholder|formatterName:arg1:arg2}}` syntax,
resolves the formatter class via FormatterBuilder, and applies it to
the value. If the formatter doesn't exist or fails, it gracefully
delegates to the next modifier in the chain.
Assisted-by: Copilot
Assisted-by: OpenCode (ollama-cloud/glm-4.7)
Assisted-by: Claude Code (Claude Opus 4.5)
892f25b to
3a9d71c
Compare
Introduce a generic FormatterModifier that dynamically instantiates and applies any formatter based on the pipe syntax. This eliminates the need to create separate modifier classes for each formatter.
The modifier parses
{{placeholder|formatterName:arg1:arg2}}syntax, resolves the formatter class via FormatterBuilder, and applies it to the value. If the formatter doesn't exist or fails, it gracefully delegates to the next modifier in the chain.Assisted-by: Copilot
Assisted-by: OpenCode (ollama-cloud/glm-4.7)
Assisted-by: Claude Code (Claude Opus 4.5)