We want to release version 3.0 as fresh as possible, without having to
maintain backward compatibility with the previous versions.
Acked-by: Alexandre Gomes Gaigalas <alganet@gmail.com>
When nested-structural validation fails, it's challenging to identify
which rule failed from the main exception message. A great example is
the `Issue796Test.php` file. The exception message says:
host must be a string
But you're left unsure whether it's the `host` key from the `mysql` key
or the `postgresql` key.
This commit changes that behaviour by introducing the concept of "Path."
The `path` represents the path that a rule has taken, and we can use it
in structural rules to identify the path of an array or object.
Here's what it looks like before and after:
```diff
-host must be a string
+`.mysql.host` must be a string
```
Because paths are a specific concept, I added a dot (`.`) at the
beginning of all paths when displaying them. I was inspired by the `jq`
syntax. I also added backticks around paths to distinguish them from any
other value.
I didn't manage to fix a test, and I skipped it instead of fixing it
because I want to make changes in how we display error messages as
arrays, and it will be easier to fix it then.
Because of how the validation engine works now [1], there's no reason to
keep adding names to each rule. Instead, create a single rule that
handles naming rules with a few other accessories. This change is not
necessarily simple, but it shrinks the `Rule` interface, and it's more
aligned with how the library works right now.
Personally, I think this API is much more straightforward than the
`setName()` method, as it's way more explicit about which rule we're
naming. Because of this change, the behaviour changed slightly, but it's
for the best.
Because of this change, I managed to remove a lot of code, but
unfortunately, it's quite a big-bang commit. It would be too complicated
to make it atomic since names are an intrinsic part of the library.
[1]: 238f2d506a
With this change, any rule can be used as a PHP attribute. I have wanted
to implement this feature for a while, as it allows you to bind the
validation to a specific property and just validate the object
afterwards.
After changes in the key-related rules, the KeySet rule became unusable.
Besides, when evaluating an input, it wasn't reporting every single
failure because it would not validate the items in the array if they had
missing or extra keys.
This commit will make several improvements to the rule. It will create
some not(keyExists($key)) rules for the extra keys, which makes the
error reporting much better. A limit of 10 additional keys will show up
when asserting an input with extra keys. I put that limit in place to
prevent the creation of too many rules.
When you have a chain of rules in the Validation and overwrite the name
with "setName()," it's impossible to get the messages from all rules in
the chain as an array because they all have the same name.
These changes will change that behavior by creating a more explicit
distinction between "IDs" and "names." The "IDs" will remain
unchangeable, while we can always overwrite the names. That means that
the array messages will look more similar to the chain, and it will be
possible to overwrite the messages from multiple rules in the same
chain.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Because of that, I also updated some data providers to distinguish
between "values" and "types", similar to some of the rules we already
have.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Currently, the Key rule has a third parameter that allows the validation
of the wrapped rule to be optional, meaning that the validation will
only happen if the key exists. That parameter makes the rule harder to
understand at times.
I'm splitting the Key rule into Key, KeyExists, and KeyOptional. That
way, it becomes apparent when someone wants only to validate whether a
key exists or if they're going to validate the value of the key only
when it exists.
I deliberately didn't create an abstract class because those rules are
different enough not to have an abstraction. In fact, I can see myself
deleting the "AbstractRelated" in the upcoming changes.
With these changes, the KeySet rule will not accept validating if the
key exists or validating the value only if the key exists. I should
refactor that soon, and I will likely need to create a common interface
for Key, KeyExists, and KeyOptional.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>