Commit 18b9c33
V3.1.0 enhancements (#42)
* Guard against empty or whitespace-only input in parseText()
When parseText() is called with an empty or whitespace-only string,
similarity matching against templates via similar_text() produces
undefined/meaningless scores and brute-force matching wastes cycles.
Return early with an empty ParseResult and log a warning instead.
* Validate PCRE named capture group names in template variables
Template variables like {%my-var%} or {%123abc%} produce invalid PCRE
named capture groups, causing silent regex failures and empty results.
Validate each variable name against /^[a-zA-Z_][a-zA-Z0-9_]*$/ in
TemplatesHelper::prepareTemplate() and throw
InvalidTemplateVariableNameException with a clear message on violation.
* Validate prepared regex pattern before returning from prepareTemplate()
User-provided regex patterns in template variables (e.g. {%id:[0-9+%})
could silently produce broken PCRE and return empty results with no
indication of the root cause. After building the final pattern, run a
dummy preg_match() and throw InvalidTemplateSyntaxException with the
PCRE error message when the pattern is invalid, enabling fast failure
instead of silent data loss.
* Cache prepared template regex patterns to avoid redundant disk I/O
Each call to parseText() previously triggered a file_get_contents() +
full regex compilation pass for every template in the directory. Add an
in-memory cache (keyed by file path) on the TemplatesHelper instance so
that subsequent parseText() calls on the same parser reuse the compiled
patterns, cutting redundant I/O and regex compilation to zero.
* Implement IteratorAggregate and Countable on ParseResult
Users previously had to call getParsedRawData() to iterate over results
or countResults() for counting. ParseResult now implements \IteratorAggregate
and \Countable so it can be used directly in foreach loops and with count(),
reducing boilerplate in consumer code.
* Add getOrFail() shorthand to ParseResult for explicit strict key access
get(\$key, true) works but requires reading the boolean argument at
every call site to understand its intent. getOrFail() expresses the
strict contract directly in its name and returns a non-nullable string,
giving callers a cleaner type signature without requiring an assertion
or null-coalesce at the call site.
* Enrich log messages with file path, text size, template count, and match outcome
Previous log messages showed only raw JSON of extracted data and a bare
template path, making it hard to debug parsing issues in production.
Log messages now include: file path and byte size in parseFileContent(),
text length and template count with similarity mode in parseText(),
template basename on each attempt, key count on a successful match,
and an explicit no-match info log when no template fits.
* Add dedicated exception tests and include Exception dir in coverage
Exception classes had no direct tests, so their inheritance chain,
message propagation, and newly added classes (InvalidTemplateSyntaxException,
InvalidTemplateVariableNameException) were unverified. ExceptionTest covers
all exception classes for correct base-class inheritance and message
preservation. Also remove the src/Exception coverage exclusion from
phpunit.xml so exception code is now tracked in the coverage report.
* Add PHPStan level-8 static analysis with composer analyse and lint scripts
PHPStan at level 8 (the strictest) is added as a dev dependency with a
phpstan.neon targeting the src/ directory. Two new composer scripts make
common quality tasks discoverable without reading docs: `composer analyse`
runs static analysis and `composer lint` checks PHP syntax across src/
and tests/. This catches type errors, dead code, and unsafe operations
before they reach CI.
* Drop composer.lock and ignore it for library repo
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>1 parent 94da5b6 commit 18b9c33
11 files changed
Lines changed: 185 additions & 1753 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
| 49 | + | |
| 50 | + | |
50 | 51 | | |
51 | 52 | | |
52 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
53 | 56 | | |
54 | 57 | | |
0 commit comments