Commit Graph

16897 Commits

Author SHA1 Message Date
Fabien Potencier c413f89723 [Console] added a better way to ask questions to the user 2014-04-01 14:31:41 +02:00
Fabien Potencier 58bed5d200 feature #10593 [Templating] Added ability to set a specific version of the asset (romainneutron)
This PR was merged into the 2.5-dev branch.

Discussion
----------

[Templating] Added ability to set a specific version of the asset

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT
| Doc PR        | https://github.com/symfony/symfony-docs/pull/3742/files

This PR replaces #6092

Commits
-------

1642094 [Templating] Update changelog
6fce503 [Templating] Added ability to set a specific version of the asset
2014-03-31 15:55:50 +02:00
Romain Neutron 1642094cfe [Templating] Update changelog 2014-03-31 15:27:29 +02:00
Martin Hasoň 6fce503432 [Templating] Added ability to set a specific version of the asset 2014-03-31 15:27:29 +02:00
Fabien Potencier 7792ba90db fixed typo in composer.json 2014-03-31 13:19:58 +02:00
Fabien Potencier bd577b11a2 feature #10287 [WIP][Validator] New NodeTraverser implementation (webmozart)
This PR was merged into the 2.5-dev branch.

Discussion
----------

[WIP][Validator] New NodeTraverser implementation

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | TODO
| License       | MIT
| Doc PR        | TODO

This PR is ready for review.

#### Todo

- [x] Test extensively to avoid regressions
- [x] Test more extensively
- [x] Finish inline documentation
- [x] Provide a layer to choose the desired API through ValidatorBuilder
- [x] Provide a layer to choose the desired API through FrameworkBundle
- [x] Update UPGRADE file
- [x] Update CHANGELOG
- [ ] Update user documentation

#### Goal

The goal of this PR is to be able to fix the following tickets:

- [x] #6138 Simplify adding of constraint violations
- [x] #7146 Support group sequences in Validator API
- [x] #7432 Poorly implemented Visitor Pattern
- [x] #8617 Control traversal on class level
- [x] #9888 Improve support for collection validation (PR: #9988)

The following tickets are probably fixed, but require testing first:

- [ ] #8376 Using validation_group causes error message to display multiple times
- [ ] #9939 GroupSequences still execute next group if first fail

Of course, full backwards compatibility **must** be guaranteed.

Other tickets I want to fix in follow-up PRs:

* #3622 Constraints\Valid does not respect "groups" option
* #4453 walk constraints by groups
* #7700 Propagate implicit group names in constraints
* #9051 Always ask value event if field isn't in the validating group
* #10163 poor collection validation test coverage
* #10221 TypeValidator does not enforce desired type when value is NULL
* #10495 Class Valid Constraint can't be used on a Form Type

#### In a nutshell

The implementation removes the Visitor pattern, which was implemented badly. I tried fixing it via a NodeTraverser/NodeVisitor implementation, but performance degraded too much so I decided to remove the pattern altogether.

A couple of new features and bug fixes are possible thanks to the new implementation. See below for details.

#### PHP Versions

PHP 5.3.8 and older does not allow to implement two different interfaces which both contain a method with the same name. This is used in the compatibility layer that supports both the old and the new API.

For this reason, the compatibility layer is disabled on PHP < 5.3.9. Older PHP versions need to decide on the old API or the new API (without compatibility layer).

#### Choosing the API Version

The API version can be specified by one of `Validation::API_VERSION_2_4`, `Validation::API_VERSION_2_5` and `Validation::API_VERSION_2_5_BC` to `setApiVersion()` when building the validator:

```php
// Old implementation
$validator = Validation::createValidatorBuilder()
    ->setApiVersion(Validation::API_VERSION_2_4)
    ->getValidator();

// New implementation with BC API
// Does not work on PHP < 5.3.9
$validator = Validation::createValidatorBuilder()
    ->setApiVersion(Validation::API_VERSION_2_5)
    ->getValidator();

// New implementation without BC API
$validator = Validation::createValidatorBuilder()
    ->setApiVersion(Validation::API_VERSION_2_5_BC)
    ->getValidator();
```

#### Features

##### Constraint validation as first-class citizen

The new API merges `validateValue()` and `validate()`. The idea is that the validation of values against constraints should be as simple as possible. Object validation is a special case where an object is tested against the `Valid` constraint. A backwards compatibility layer is provided to use both `validate()` and `validateValue()` with the old signature.

```php
// Validate against explicit constraints
$violations = $validator->validate($firstName, array(
    new NotNull(),
    new Length(array('min' => 3)),
));

// Validate against metadata
$violations = $validator->validate($object);

// Same, more expressive notation
$violations = $validator->validate($object, new Valid());

// Validate each entry against its metadata
$violations = $validator->validate($array);
```

##### Aggregate violations

It is now possible to call the methods of the validator multiple times and aggregate the violations to a common violation list. To do so, call `startContext()`, execute the calls and call `getViolations()` in the end to retrieve the violations:

```php
$violations = $validator->startContext()
    ->validate($title, new NotNull())
    ->validate($text, new NotNull())
    ->validate($author->getName(), new NotNull())
    ->getViolations()
```

Most of the time, you will want to specify a property path for each validation. Use the method `atPath()` for that:

```php
$violations = $validator->startContext()
    ->atPath('title')->validate($title, new NotNull())
    ->atPath('text')->validate($text, new NotNull())
    ->atPath('author.name')->validate($author->getName(), new NotNull())
    ->getViolations()
```

##### Control the context of nested validations

In Symfony <= 2.4, you can validate objects or constraints from within a constraint validator like this:

```php
$this->context->validate($object);
$this->context->validateValue($value, new Length(array('min' => 3)));
```

The validations will run and all violations will be added to the current context.

This way, it is impossible though to validate something, inspect the result and then decide what kind of violations to add to the context. This is needed, for example, for the `Some` constraint (proposed in #9888), which should succeed if any of the validated values did *not* generate violations.

For this reason, the new context API features a method `getValidator()`. This method returns the validator instance, you can use it to validate anything in a new context (as the validator always does):

```php
$validator = $this->context->getValidator();
$violations = $validator->validate($object);

if (count($violations)  > 0) {
    $this->context->addViolation('The validation did not pass');
}
```

You can also explicitly start a new context:

```php
$validator = $this->context->getValidator();
$violations = $validator->startContext()
    ->atPath('title')->validate($title, new NotNull())
    ->atPath('text')->validate($text, new NotNull())
    ->getViolations()
```

If you want to execute the validation in the current context, use the `inContext()` method of the validator instead:

```php
// violations are added to $this->context
$validator->inContext($this->context)
    ->atPath('title')->validate($title, new NotNull())
    ->atPath('text')->validate($text, new NotNull())
;
```

With this feature, #9888 (especially the PR for it: #9988) can be finished.

##### Custom group sequences (#7146)

It is now possible to pass `GroupSequence` instances whenever you can pass a group to the validator. For example:

```php
$violations = $validator->validate($object, new Valid(), new GroupSequence('Basic', 'Strict'));
```

Or in the context of the Form component:

```php
$form = $this->createForm(new BlogType(), new Blog(), array(
    'validation_groups' => new GroupSequence('Basic', 'Strict'),
));
```

##### Constraint violation builders (#6138)

The API for adding constraint violations was simplified:

```php
$this->context->addViolation('message', array('param' => 'value'));

// or

$this->context->buildViolation('message')
    ->atPath('property')
    ->setParameter('param', 'value')
    ->setTranslationDomain('validation_strict')
    ->addViolation();
```

##### Control traversal at class level (#8617)

Currently, it is possible whether to traverse a `Traversable` object or not in the `Valid` constraint:

```php
/**
 * @Assert\Valid(traverse=true)
 */
private $tags = new TagList();
```

(actually, `true` is the default)

In this way, the validator will iterate the `TagList` instance and validate each of the contained objects. You can also set "traverse" to `false` to disable iteration.

What if you want to specify, that `TagList` instances should always (or never) be traversed? That's currently not possible.

With this PR, you can do the following:

```php
/**
 * @Assert\Traverse(false)
 */
class TagList implements \IteratorAggregate
{
    // ...
}
```

#### Follow-up features

Features of the follow-up PRs will be described directly there.

#### Backwards compatibility

I implemented a new `AbstractValidatorTest` which tests both the old and the new implementation for compatibility. I still want to extend this test to make sure we don't introduce any regressions.

Almost none of the existing classes were modified (or only slightly). If users depend on the current (now "legacy") implementation, they will have the choice to continue using it until 3.0 (of course, without the new features).

#### Your task

Congrats, you made it till here :) If you have time, please skim over the code and give me feedback on the overall implementation and the class/method names. Again, no feedback on details yet, there are quite a few areas in the code that are still work in progress.

Thanks,
Bernhard

[1] That means that only the nodes from the root of the graph until the currently validated node are held in memory.

Commits
-------

ca6a722 [Validator] Converted `@deprecate` doc comment into regular doc comment
68d8018 [Validator] Documented changes in the UPGRADE files
b1badea [Validator] Fixed failing CsrfFormLoginTest
0bfde4a [Validator] Fixed misnamed method calls in FrameworkExtension
3dc2b4d [Validator] Made "symfony/property-access" an optional dependency
c5629bb [Validator] Added getObject() to ExecutionContextInterface
9b204c9 [FrameworkBundle] Implemented configuration to select the desired Validator API
0946dbe [Validator] Adapted CHANGELOG
1b111d0 [Validator] Fixed typos pointed out by @cordoval
7bc952d [Validator] Improved inline documentation of RecursiveContextualValidator
166d71a [Validator] Removed unused property
90c27bb [Validator] Removed traverser implementation
3183aed [Validator] Improved performance of cache key generation
029a716 [Validator] Moved logic of replaceDefaultGroup() to validateNode()
2f23d97 [Validator] Reduced number of method calls on the execution context
73c9cc5 [Validator] Optimized performance by calling spl_object_hash() only once per object
94ef21e [Validator] Optimized use statements
1622eb3 [Validator] Fixed reference to removed class in ValidatorBuilder
be508e0 [Validator] Merged DefaultGroupReplacingVisitor and ContextUpdateVisitor into NodeValidationVisitor
50bb84d [Validator] Optimized RecursiveContextualValidator
eed29d8 [Validator] Improved performance of *ContextualValidator::validate()
5c479d8 [Validator] Simplified validateNodeForGroup
eeed509 [Validator] Improved phpdoc of RecursiveValidator
274d4e6 [Validator] Changed ValidatorBuilder to always use LegacyExecutionContext
38e26fb [Validator] Decoupled RecursiveContextualValidator from Node
23534ca [Validator] Added a recursive clone of the new implementation for speed comparison
f61d31e [Validator] Fixed grammar
886e05e [Validator] Removed unused use statement
93fdff7 [Validator] The supported API versions can now be passed to the ValidatorBuilder
987313d [Validator] Improved inline documentation of the violation builder
79387a7 [Validator] Improved inline documentation of the metadata classes
01ceeda [Validator] Improved test coverage of the Traverse constraint
9ca61df [Validator] Improved inline documentation of CascadingStrategy and TraversalStrategy
524a953 [Validator] Improved inline documentation of the validators
9986f03 [Validator] Added inline documentation for the PropertyPath utility class
be7f055 [Validator] Visitors may now abort the traversal by returning false from beforeTraversal()
299c2dc [Validator] Improved test coverage and prevented duplicate validation of constraints
186c115 [Validator] Improved test coverage of NonRecursiveNodeTraverser
822fe47 [Validator] Completed inline documentation of the Node classes and the NodeTraverser
dbce5a2 [Validator] Updated outdated doc blocks
8558377 [Validator] Added deprecation notes
e8fa15b [Validator] Fixed the new validator API under PHP < 5.3.9
2936d10 [Validator] Removed unused use statement
6fc6ecd [Validator] Fixed tests under PHP<5.3.9
778ec24 [Validator] Removed helper class Traversal
76d8c9a [Validator] Fixed typos
4161371 [Validator] Removed unused use statements
aeb6822 [Validator] Improved visitor names
08172bf [Validator] Merged validate(), validateObject() and validateObjects() to simplify usage
51197f6 [Validator] Made traversal of Traversables consistent
117b1b9 [Validator] Wrapped collections into CollectionNode instances
94583a9 [Validator] Changed NodeTraverser to traverse nodes iteratively, not recursively
cf1281f [Validator] Added "Visitor" suffix to all node visitors
230f2a7 [Validator] Fixed exception message
e057b19 [Validator] Decoupled ContextRefresher from ExecutionContext
e440690 [Validator] Renamed validateCollection() to validateObjects()
df41974 [Validator] Changed context manager to context factory
26eafa4 [Validator] Removed unused use statements
bc29591 [Validator] Clearly separated classes supporting the API <2.5/2.5+
a3555fb [Validator] Fixed: Objects are not traversed unless they are instances of Traversable
2c65a28 [Validator] Completed test coverage and documentation of the Node classes
9c9e715 [Validator] Completed documentation of GroupManagerInterface
1e81f3b [Validator] Finished test coverage and documentation of ExecutionContextManager
feb3d6f [Validator] Tested the validation in a separate context
718601c [Validator] Changed validateValue() to validate() in the new API
ee1adad [Validator] Implemented handling of arrays and Traversables in LegacyExecutionContext::validate()
09f744b [Validator] Implemented BC traversal of traversables through validate()
297ba4f [Validator] Added a note why scalars are passed to cascadeObject() in NodeTraverser
9b07b0c [Validator] Implemented BC validation of arrays through validate()
405a03b [Validator] Updated deprecation notes in GroupSequence
499b2bb [Validator] Completed test coverage of ExecutionContext
adc1437 [Validator] Fixed failing tests
4ea3ff6 [Validator] Finished inline documentation of ExecutionContext[Interface]
f6b7288 [Validator] Removed unused use statement
8318286 [Validator] Completed GroupSequence implementation
5fbf848 [Validator] Added note about Callback constraint to CHANGELOG
c1b1e03 [Validator] Added TODO reminder
8ae68c9 [Validator] Made tests green (yay!)
680f1ee [Validator] Renamed $params to $parameters
321d5bb [Validator] Throw exception if ObjectInitializer is constructed without visitors
1156bde [Validator] Extracted code for group sequence resolving into GroupSequenceResolver
b1a9477 [Validator] Added ObjectInitializer visitor
7e3a41d [Validator] Moved visitors to NodeVisitor namespace
a40189c [Validator] Decoupled the new classes a bit
a6ed4ca [Validator] Prototype of the traverser implementation
25cdc68 [Validator] Refactored ValidatorTest and ValidationVisitorTest into an abstract validator test class
2014-03-31 13:08:13 +02:00
Fabien Potencier 880880b838 feature #10569 [Form] Accept interfaces to be passed to "data_class" (webmozart)
This PR was merged into the 2.5-dev branch.

Discussion
----------

[Form] Accept interfaces to be passed to "data_class"

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8669
| License       | MIT
| Doc PR        | -

Commits
-------

b44e07b [Form] Added test case for 4759e062ed004749dbdc2ba31aef0f8ac2601895
7bc7a8a [Form] Accept interfaces to be passed to "data_class"
2014-03-31 13:06:03 +02:00
Fabien Potencier c5a3008123 feature #10570 [PropertyAccess] Added isReadable() and isWritable() (webmozart)
This PR was merged into the 2.5-dev branch.

Discussion
----------

[PropertyAccess] Added isReadable() and isWritable()

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8659
| License       | MIT
| Doc PR        | symfony/symfony-docs#3729

This PR introduces BC breaks that are described in detail in the UPGRADE file. The BC breaks conform to our policy. They shouldn't affect many people, so I think we can safely do them.

Commits
-------

f7fb855 [PropertyAccess] Added missing exceptions to phpdoc
9aee2ad [PropertyAccess] Removed the argument $value from isWritable()
4262707 [PropertyAccess] Fixed CS and added missing documentation
6d2af21 [PropertyAccess] Added isReadable() and isWritable()
20e6bf8 [PropertyAccess] Refactored PropertyAccessorCollectionTest
0488389 [PropertyAccess] Refactored PropertyAccessorTest
2014-03-31 13:04:12 +02:00
Fabien Potencier 2ab27aba8b feature #10572 [Form] ObjectChoiceList now compares choices by their value, if a value path is given (webmozart)
This PR was merged into the 2.5-dev branch.

Discussion
----------

[Form] ObjectChoiceList now compares choices by their value, if a value path is given

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8825
| License       | MIT
| Doc PR        | -

Commits
-------

ce0efb1 [Form] ObjectChoiceList now compares choices by their value, if a value path is given
2014-03-31 12:59:41 +02:00
Fabien Potencier bafced661f bug #10567 [Form] Disabled validation/violation mapping of unsubmitted forms (webmozart)
This PR was merged into the 2.5-dev branch.

Discussion
----------

[Form] Disabled validation/violation mapping of unsubmitted forms

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9998
| License       | MIT
| Doc PR        | -

This PR fixes submissions of PATCH form in the case that any of the non-submitted forms causes an error (such as not-null).

Commits
-------

9dfebd5 [Form] Disabled violation mapping of unsubmitted forms
2014-03-31 12:13:10 +02:00
Bernhard Schussek f7fb855f46 [PropertyAccess] Added missing exceptions to phpdoc 2014-03-31 10:36:17 +02:00
Bernhard Schussek 9dfebd529e [Form] Disabled violation mapping of unsubmitted forms 2014-03-31 10:27:06 +02:00
Bernhard Schussek ca6a722a45 [Validator] Converted `@deprecate` doc comment into regular doc comment 2014-03-30 20:08:02 +02:00
Bernhard Schussek 68d80187ed [Validator] Documented changes in the UPGRADE files 2014-03-30 20:03:32 +02:00
Bernhard Schussek b1badeaa1f [Validator] Fixed failing CsrfFormLoginTest 2014-03-30 18:56:20 +02:00
Bernhard Schussek 0bfde4a44b [Validator] Fixed misnamed method calls in FrameworkExtension 2014-03-30 18:31:31 +02:00
Bernhard Schussek 3dc2b4d861 [Validator] Made "symfony/property-access" an optional dependency 2014-03-30 18:31:31 +02:00
Bernhard Schussek c5629bb7ee [Validator] Added getObject() to ExecutionContextInterface 2014-03-30 18:31:00 +02:00
Bernhard Schussek 9b204c9354 [FrameworkBundle] Implemented configuration to select the desired Validator API 2014-03-30 18:31:00 +02:00
Bernhard Schussek 0946dbe7a0 [Validator] Adapted CHANGELOG 2014-03-30 18:30:09 +02:00
Bernhard Schussek 1b111d0e83 [Validator] Fixed typos pointed out by @cordoval 2014-03-30 18:30:09 +02:00
Bernhard Schussek 7bc952de55 [Validator] Improved inline documentation of RecursiveContextualValidator 2014-03-30 18:30:09 +02:00
Bernhard Schussek 166d71a7de [Validator] Removed unused property 2014-03-30 18:30:09 +02:00
Bernhard Schussek 90c27bb1e7 [Validator] Removed traverser implementation
The traverser is too slow compared to the current, recursive approach.
Testing showed a performance decrease of about 70% without a lot of
optimization potential.
2014-03-30 18:30:09 +02:00
Bernhard Schussek 3183aed7cd [Validator] Improved performance of cache key generation 2014-03-30 18:30:09 +02:00
Bernhard Schussek 029a71638e [Validator] Moved logic of replaceDefaultGroup() to validateNode() 2014-03-30 18:30:09 +02:00
Bernhard Schussek 2f23d9725b [Validator] Reduced number of method calls on the execution context 2014-03-30 18:30:09 +02:00
Bernhard Schussek 73c9cc5806 [Validator] Optimized performance by calling spl_object_hash() only once per object 2014-03-30 18:30:09 +02:00
Bernhard Schussek 94ef21e495 [Validator] Optimized use statements 2014-03-30 18:30:09 +02:00
Bernhard Schussek 1622eb3a98 [Validator] Fixed reference to removed class in ValidatorBuilder 2014-03-30 18:28:59 +02:00
Bernhard Schussek be508e01dd [Validator] Merged DefaultGroupReplacingVisitor and ContextUpdateVisitor into NodeValidationVisitor 2014-03-30 18:28:59 +02:00
Bernhard Schussek 50bb84d06b [Validator] Optimized RecursiveContextualValidator 2014-03-30 18:28:59 +02:00
Bernhard Schussek eed29d8ad3 [Validator] Improved performance of *ContextualValidator::validate() 2014-03-30 18:28:59 +02:00
Bernhard Schussek 5c479d803c [Validator] Simplified validateNodeForGroup 2014-03-30 18:28:59 +02:00
Bernhard Schussek eeed509dfc [Validator] Improved phpdoc of RecursiveValidator 2014-03-30 18:28:59 +02:00
Bernhard Schussek 274d4e6195 [Validator] Changed ValidatorBuilder to always use LegacyExecutionContext
This is necessary because, until Symfony 3.0, constraint validators will continue
to rely on the old context methods in order to be backwards compatible.
2014-03-30 18:28:59 +02:00
Bernhard Schussek 38e26fbcaf [Validator] Decoupled RecursiveContextualValidator from Node 2014-03-30 18:28:59 +02:00
Bernhard Schussek 23534ca6ab [Validator] Added a recursive clone of the new implementation for speed comparison 2014-03-30 18:28:59 +02:00
Bernhard Schussek f61d31e5fa [Validator] Fixed grammar 2014-03-30 18:28:58 +02:00
Bernhard Schussek 886e05e7ed [Validator] Removed unused use statement 2014-03-30 18:28:58 +02:00
Bernhard Schussek 93fdff764a [Validator] The supported API versions can now be passed to the ValidatorBuilder 2014-03-30 18:28:58 +02:00
Bernhard Schussek 987313d315 [Validator] Improved inline documentation of the violation builder 2014-03-30 18:28:58 +02:00
Bernhard Schussek 79387a7d5e [Validator] Improved inline documentation of the metadata classes 2014-03-30 18:28:58 +02:00
Bernhard Schussek 01ceeda376 [Validator] Improved test coverage of the Traverse constraint 2014-03-30 18:28:58 +02:00
Bernhard Schussek 9ca61df923 [Validator] Improved inline documentation of CascadingStrategy and TraversalStrategy 2014-03-30 18:28:58 +02:00
Bernhard Schussek 524a9538bc [Validator] Improved inline documentation of the validators 2014-03-30 18:28:58 +02:00
Bernhard Schussek 9986f03ce2 [Validator] Added inline documentation for the PropertyPath utility class 2014-03-30 18:28:58 +02:00
Bernhard Schussek be7f055237 [Validator] Visitors may now abort the traversal by returning false from beforeTraversal() 2014-03-30 18:28:58 +02:00
Bernhard Schussek 299c2dca10 [Validator] Improved test coverage and prevented duplicate validation of constraints 2014-03-30 18:28:58 +02:00
Bernhard Schussek 186c115894 [Validator] Improved test coverage of NonRecursiveNodeTraverser 2014-03-30 18:28:58 +02:00