Commit graph

6 commits

Author SHA1 Message Date
Henrique Moody
d4605f4493
Add wildcard support to ResultQuery::findByPath()
Before this change, querying validation results required knowing the
exact path to a specific result node—including numeric indices for
array elements (e.g., `items.1.email`). This made it impractical to
locate the first failing result in dynamic collections where the
failing index is not known ahead of time.

Wildcard segments (`*`) allow matching any single path component, so
patterns like `items.*`, `*.email`, or `data.*.value` will traverse
the result tree and return the first node whose path matches. This is
particularly valuable when validating arrays of items with `each()`,
because consumers can now ask "give me the first failure under items"
without iterating manually.

The implementation replaces the previous flat `array_find` lookup with
a recursive depth-first traversal that, when a wildcard is present,
compares each node's full path against the pattern using segment-level
matching. Non-wildcard lookups continue to use exact array equality,
so there is no behavioral change for existing callers.

Assisted-by: Claude Code (claude-opus-4-6)
2026-02-08 22:43:06 +01:00
Henrique Moody
7c681fec66
Fix SPDX headers in all files
I ran the `bin/console spdx --fix` with different strategies for
different files. For most of the core classes, since they've been
drastically rebuilt, I've run it with the `git-blame` strategy, for for
the `src/Validators`, in which the API changed completely but the logic
remains the same, I use the `git-log` strategy.
2026-02-03 15:23:23 +01:00
Henrique Moody
00e7f2a6ff
Fix ResultQuery::findByPath() for nested paths
The `findByPath()` method was failing to return results when using nested
dot-notation paths such as `user.email` or `items.1`. However, it’s returning
`null` instead of the expected result in some cases.

The root cause was a mismatch between how paths are stored vs searched:

- Storage: Validators like Key and Each create results where the path is stored
  as a linked list. For `user.email`, the "email" result has `path="email"` with
  `parent="user"`.

- Search (old): The method expected a tree structure where it would find a child
  with `path="user"`, then search that child for `path="email"`. But no child
  had `path="user"` - only "email" (with "user" as its parent).

The fix computes each result's full path by walking up the parent chain and
compares it against the search path. Also converts numeric strings to integers
when parsing paths (e.g., `items.1` → `['items', 1]`) since array indices are
stored as integers.

While working on this fix, I also realised that to expose the result's status,
it’s best to use `hasFailed()` instead of `isValid()` in `ResultQuery`, since
users will mostly use results when validation failed, not when it passed.

Assisted-by: Claude Code (Opus 4.5)
2026-01-27 13:25:40 +01:00
Henrique Moody
a372a0b90b
Replace template rendering code with Respect\StringFormatter
I've moved almost all the code for placeholder replacement and parameter
modifiers into an external library called Respect\StringFormatter. This approach
allows us to evolve the template capabilities without making major changes to the
Validation's code.

This commit will introduce another dependency, `respect/string-formatter`, and
will upgrade the version of `respect/string-formatter`, which simplifies our
internal API greatly.

While making this change, I also updated how we generate exceptions. Instead of
rendering the full message and the array of messages, we delegate that creation
to the `ResultQuery`, which improves performance because we don’t need to render
those big messages unless the user actually needs them.
2026-01-21 17:29:15 +01:00
Alexandre Gomes Gaigalas
d9cdc118b2 Introduce REUSE compliance
This commit introduces REUSE compliance by annotating all files
with SPDX information and placing the reused licences in the
LICENSES folder.

We additionally removed the docheader tool which is made obsolete
by this change.

The main LICENSE and copyright text of the project is now not under
my personal name anymore, and it belongs to "The Respect Project
Contributors" instead.

This change restores author names to several files, giving the
appropriate attribution for contributions.
2026-01-21 06:28:11 +00:00
Henrique Moody
16c2a75d00
Enable validating inputs without throwing exceptions
Currently, the only way to handle when a validation fails is by
`assert()`, which either throws an exception or doesn't. That means that
every time a user wants to handle the results, they must use try-catch
blocks, which may add some overhead.

This commit introduces the `ResultQuery` class that wraps a `Result`
object, providing an alternative to exception-based validation. This
allows users to handle results directly without try-catch blocks.

I’m taking a risky move here using the old method `validate()`, but I
can’t think of a better name for this method.
2025-12-22 20:37:11 +01:00