This commit introduces a mechanism for validators to return early once
the validation outcome is determined, rather than evaluating all child
validators.
The ShortCircuit validator evaluates validators sequentially and stops
at the first failure, similar to how PHP's && operator works. This is
useful when later validators depend on earlier ones passing, or when
you want only the first error message.
The ShortCircuitCapable interface allows composite validators (AllOf,
AnyOf, OneOf, NoneOf, Each, All) to implement their own short-circuit
logic.
Why "ShortCircuit" instead of "FailFast":
The name "FailFast" was initially considered but proved misleading.
While AllOf stops on failure (fail fast), AnyOf stops on success
(succeed fast), and OneOf stops on the second success. The common
behavior is not about failing quickly, but about returning as soon as
the outcome is determined—which is exactly what short-circuit
evaluation means. This terminology is familiar to developers from
boolean operators (&& and ||), making the behavior immediately
understandable.
Co-authored-by: Alexandre Gomes Gaigalas <alganet@gmail.com>
Assisted-by: Claude Code (Opus 4.5)
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.
The Prefix transformer had many loops that could be avoided. This
change replaces them for a compiled PCRE regex, taking advantage
of recent PCRE JIT capabilities introduced in PHP.
These changes offer no performance trade-offs, improving lookup
for all categories of prefixes (property/key with shift, ignore
list and fallback to simple rule).
The most affected is the simple rule (no prefix or no conflict
with any kind of prefix rule), yielding the most gains.
This commit removes validators described in #1642, refactoring
to clean up after their removal.
- Url was refactored to use the function `filter_var` instead.
- tests/bootstrap.php is no longer needed and was removed.
- Updated migration guide with recommendations for replacements.
The main focus of this change is to make those optional dependencies
more testable.
Unfortunately, some phpstan-ignores had to be included, since ::set
is not a PsrContainer method. We're only using it on tests though,
so it's fine. It targets our php-di container for testing purposes
only. The real implementation only relies on ::get.
This change also has the side effect of improving the performance
of those validators by not instantiating their databases each time
a iso validator is built, achieving massive improvements in those
scenarios. A small benchmark with no assertions was added to track
that improvement.
A new workflow, continuous-integration-perf.yml was introduced. It:
- Checks out the `benchmarks` branch locally.
- Runs the benchmarks, accounting for non-existant baselines
and target (main/PR).
- Stores the .phpbench storage folder and a human-readable
report in the `benchmarks` branch.
- Does not make a PR fail, and never reports a failure
when merging to main.
- Allows workflow_dispatch for quick re-runs, and has an
option to reset the baseline in case something changes
(GitHub runner setup gets faster/slower, major refactors,
etc).
Thus, it keeps a historical record of all benchmark results.
These results can be viewed by exploring GitHub via the web
interface and seeing the changes in `latest.md` (the human
file commited).
Additionally, one can clone the `benchmarks` branch and run
`phpbench log` to explore the history in more detail.
Some adjustments to previously added benchmarks were made:
- Assertions were included in order to track time and memory
tresholds.
- The benchmarks are now more surgical, and address the
concrete validators instead of the whole chain validate.
These changes were made to make benchmarks more isolated, with
the intention of adding chain-related benchmarks separately
in the future.
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.
This commit introduces a new feature test: SerializableTest, that
tests several validators for their ability to be serialized and
unserialized.
It also makes it so that the same list of validators can be used
by both simple benchmarks and "smoke tests" of all kinds, including
this serialize/unserialize one.
Additionally, the FilterVar validator was modified. Previously, due
to the use of Callback, it was not serializable, but now it is.
This validator is similar to Contains, but also checks how many
times the needle appears.
Additionally, the Domain validator was changed to use it instead
of relying on an unserializable callback, thus, making it
serializable.
This commit is the first step in setting up *Continuous Performance*
for the repository.
- Adds phpbench/phpbench to dev dependencies.
- Adds an initial `ValidatorBench.php` file with validate benchmarks
for several validators.
- Adds `composer bench` script to run benchmarks.
- Adds `composer bench:profile` script to generate profiles.