This commit will rename the "Nullable" rule to "NullOr" while soft
deprecating the old name. It should work the same as the previous one
but with a different name. It will also prefix the result ID, allowing
more message customization.
While working on it, I realized that the prefix "nullOr" had a typo,
and it was using "nullOf" instead. I fixed that, too.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit will rename the "Optional" rule to"UndefOr" while soft
deprecating the old name. It should work the same as the previous one
but with a different name. It will also prefix the result ID, allowing
more message customization.
While working on it, I realized that the prefix "undefOr" had a typo,
and it was using "undefOf" instead. I fixed that, too.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Because some rules work more as a prefix, it makes sense to prefix their
result ID. That will allow for a more intuitive templating, especially
when using those rules as prefixes.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
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>
When creating a result with a sibling in the When rule, the result
generates an unhelpful message. In most of the use cases of the When
rule, the initial rule ("when") is only helpful in determining which
will be the "real" rule to use.
Those changes will change the When rule not to generate results with
siblings.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
When converting an object into an array, we exclude the message root
message from it. Since we're using a convention to template those
messages as an array, we could also use the same convention to return
those messages.
While working on it, I noticed that the name "__self__" wasn't
reflecting what that really meant, so I renamed it "__root__" because it
better reflects the meaning of those messages/templates.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
After many refactorings, no rules use the previous validation engine.
That means we can remove the unused code from the repository and switch
from the previous to the new validation engine everywhere.
This commit will also soft deprecate the methods "validate()", and
"check()" in all the rules and the "assert()" in all rules but the
Validator itself. That means using those methods will still be allowed,
but static analysis tools might complain.
This is a big step toward releasing the next major version, as the code
is pretty much the way it should be when I release the next version.
There's some documentation to be updated, and I would like to change the
behavior of a couple of rules.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This commit will improve the Phone rule in the following ways:
* Upgrade its validation engine;
* Increase the number of tests;
* Do not validate phone numbers from other regions.
The last item is a possible bug with "libphonenumber-for-php", which I
have already reported.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Although helpful, the changes in the Min, Max, and Length rules made
using those rules more verbose. This commit will simplify their use by
allowing users to use them as prefixes.
Because I was creating prefixes for those rules, I made other cool
prefixes. Doing that is scary because it will generate more code to
support, and I would have liked to avoid that. However, that's a
valuable addition, and it's worth the risk.
I might reconsider that in the future, but for now, that looks like a
good idea.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Currently, the Length rule does multiple things, yet it's limited.
Because it does many things, it's also confusing. Turning the Length
rule into a transformation allows for way more flexibility and clarity.
The syntax becomes more verbose, but I can solve that later by creating
a Transformer enables creating rules with the "length" as a prefix.
While making this change, I also removed the support for counting
objects and integers. I find that way too confusing.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
For now, those transformers will help transition from the current major
version to the next. As I'm making so many changes to the behaviour of
the rules and renaming others, it could be overwhelming to update all of
them suddenly.
The Transformers will change the rules' specifications before the
Factory creates them, allowing us to keep the behaviour of the old rules
-- even if a little bit different -- while triggering E_USER_DEPRECATED
errors to indicate that the client needs to update their code until the
next major version.
However, those transformers will do more shortly, for example, allowing
us to prefix rules to make it easier to create complex rules, like
`notPositive()` or even `keyBetween('foo', 1, 10)` and so on.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Unfortunately, we can't automatically run PHPStan in the PHPT files
because it will complain about the "strict_types" not being declared as
the first part of the file. I did some workaround that and fixed some
issues.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
I also decided to make the messages way more straightforward than
before. Instead of showing why the input is not a valid domain, we're
now simply saying that the input is not a proper domain.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
With this and the Lazy rule, the LazyConsecutive lost its purpose.
While working on it, I did refactor the Domain rule a bit, but mainly to
check how this rule could behave.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This rule resembles a proper replacement for the old "KeyValue" rule
rather than the "LazyConsecutive" rule[1]. I will soon delete the
"LazyConsecutive" rule and replace it with something else.
[1]: 41245f663f
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Because we have the Key and Property rules, the KeyNested is redundant,
although it's a helpful shortcut.
The real problem is dealing with messages and templates because the
structure of the validator needs to match the structure of the rule.
When using the `getMessages()` method from the exception we throw in
`assert()`, we get a flat structure, which is often not the intended
structure.
The KeyNested rule is cool, but it adds some complexity to the codebase
that I'm unwilling to deal with. It's not nice to remove a rule,
especially because I know people use it, but it's for the best. I'm
trying to keep the codebase small, so hopefully, it will get easier to
maintain.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Currently, the Property 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 property exists. That parameter makes
the rule harder to understand at times.
I'm splitting the Property rule into Property, PropertyExists, and
PropertyOptional. That way, it becomes apparent when someone wants only
to validate whether a property exists or if they will validate the value
of the property 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 after I refactor the KeyNested rule.
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>
The "Max" rule is not a transformation, validating the maximum value in
the input against a given rule.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
These changes will also introduce an abstract rule that validates
non-empty-iterable values. The abstract rule can also be the parent of
the recently created "Min" rule. Therefore, I've changed that class too.
I've introduced many tests for the "Each" rule to make sure what its
expected behavior is. I'm not super happy with its output, but I tried a
couple of options, and it is the best choice.
Note that Each now rejects `stdClass` and empty iterable values. I
thought that would make sense, as it would be useless when the input is
empty.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
The difference with this rule is that it matches the behavior of
`is_iterable()`, which is different from `IterableVal` that also allows
instances of `stdClass.`
This is a necessary change because PHP will trigger an error when trying
to pass any object to anything typed as `iterable`
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
When we created this rule in version 1.0 in 2015, PHP was in version
5.6, and the `is_iterable()` function didn't exist. Only in version 7.1,
released at the end of 2016, was the pseudo-type "iterable" introduced
to PHP.
This old "IterableType" rule is almost obsolete. Still, I decided to
keep it because it is possible to use foreach in any object, as it will
iterate over its public properties. I did rename the rule because that
makes more sense. An "IterableType" rule should guarantee that the input
type is the real-(pseudo)-iterable.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
With this rule, we introduce a new type of rule, which is only possible
due to the changes in the validation engine.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Although the name is much longer, it's more explicit what it does. I
confess that after a while without using Validation, even I get confused
about that. Besides, I would like to create another rule with the same
name, but that will behave differently.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Although the name is much longer, it's more explicit what it does. I
confess that after a while without using Validation, even I get confused
about that. Besides, I would like to create another rule with the same
name, but that will behave differently.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This change will also make the composite-based rules require at least
two rules in their constructor because those rules do not make sense
with only one rule.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
I want to avoid having the Factory inside the rules. If a rule needs to
create another, it can simply instantiate that. The "KeyValue" rule does
too many things under the hood, and the behavior can be unpredictable.
The "LazyConsecutive" rule makes the validation more explicit and way
more flexible, as there could be other cases in which someone only wants
to validate something if the previous validator passes.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Since we now have PHP ISO Codes as a dependency[1], it doesn't make
sense to keep dealing with this data ourselves.
[1]: 04b2722d02
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
There are a few "problems" with the current engine:
- Allowing each rule to execute assert() and check() means duplication
in some cases.
- Because we use exceptions to assert/check, we can only invert a
validation (with Not) if there are errors. That means that we have
limited granularity control.
- There is a lot of logic in the exceptions. That means that even after
it throws an exception, something could still happen. We're stable on
that front, but I want to simplify them. Besides, debugging exception
code is painful because the stack trace does not go beyond the
exception.
Apart from that, there are many limitations with templating, and working
that out in the current implementation makes it much harder.
These changes will improve the library in many aspects, but they will
also change the behavior and break backward compatibility. However,
that's a price I'm willing to pay for the improvements we'll have.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
With this change, we can test showing the main, full, and array messages
with a single definition. It also makes the scenario we're trying to
test clear, because we describe it with text.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
The `print_r()` is noisy and doesn't show values as they are in PHP, and
using `VarExporter::export()` improved the output a lot.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
In some cases, a user would like to show the parameter just as it is,
and in other cases, they need to translate a specific parameter. This
change creates that capability by adding a template-style modifier to a
parameter in the template.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Some integration tests did not use the standard functions for testing
exceptions in PHPT files. This change will make all integration tests
more uniform, which will help me change the internal validation engine
later.
This change will also unify the integration tests for "Between" into a
single file and a few other improvements.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Most of those files have undergone massive changes; in some cases, the
"--CREDITS--" might not make sense.
This is aligned with the latest coding standard changes [1], since we no
longer allow the annotation "@author".
In any case, we can always use `git blame` or `git log` to see the
contributors.
[1]: 9a13c9fb03
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Because now we have the concept of attributes in PHP, the rule with the
name "Attribute" makes no sense because it doesn't validate attributes
but properties.
In the future, it might be possible that Validation will have a rule
called "Attribute" to validate PHP attributes.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
The class had too much complexity and some duplication on its children.
I started doing this because I'm refactoring the tests to upgrade
PHPUnit later, and then I made some improvements along the way.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
This change will bring many breaking changes. The good thing is that we
can finally use more modern resources available in PHP.
I can imagine that's not a popular change since it will bring many
breaking changes to users, but we shouldn't be stuck in time because of
that. Using some of those features will make it easier to contribute to
the project. At least, I hope so.
There are still some useless doc-blocks, and we're not using "readonly"
properties when we could. I aim to send those changes soon.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
The integration tests use the same pattern to test exception messages.
With my changes, we won't validate which exception we throw in those
tests, but matching the message is enough. I created three functions to
replace most of those tests.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Most exception messages in Validation use "must" and "must not" in their
templates, but a few rules don't.
I fixed most of them, but AlwaysValid and AlwaysInvalid remain because I
wonder if they will be better if I update them.
Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
Doing regex on phone numbers is not a great idea. This is a breaking
change, but a good one. Phone validation is now much stricter, and
allows choosing the country.