[Validator] Improved inline documentation of the metadata classes

This commit is contained in:
Bernhard Schussek 2014-02-21 18:00:47 +01:00
parent 01ceeda376
commit 79387a7d5e
13 changed files with 331 additions and 89 deletions

View File

@ -11,25 +11,30 @@
namespace Symfony\Component\Validator\Mapping;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\MetadataFactoryInterface;
/**
* Simple implementation of MetadataFactoryInterface that can be used when using ValidatorInterface::validateValue().
* Metadata factory that does not store metadata.
*
* This implementation is useful if you want to validate values against
* constraints only and you don't need to add constraints to classes and
* properties.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class BlackholeMetadataFactory implements MetadataFactoryInterface
{
/**
* @inheritdoc
* {@inheritdoc}
*/
public function getMetadataFor($value)
{
throw new \LogicException('BlackholeClassMetadataFactory only works with ValidatorInterface::validateValue().');
throw new NoSuchMetadataException('This class does not support metadata.');
}
/**
* @inheritdoc
* {@inheritdoc}
*/
public function hasMetadataFor($value)
{

View File

@ -22,7 +22,9 @@ use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\GroupDefinitionException;
/**
* Represents all the configured constraints on a given class.
* Default implementation of {@link ClassMetadataInterface}.
*
* This class supports serialization and cloning.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Fabien Potencier <fabien@symfony.com>
@ -31,36 +33,64 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
{
/**
* @var string
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getClassName()} instead.
*/
public $name;
/**
* @var string
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getDefaultGroup()} instead.
*/
public $defaultGroup;
/**
* @var MemberMetadata[]
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getPropertyMetadata()} instead.
*/
public $members = array();
/**
* @var PropertyMetadata[]
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getPropertyMetadata()} instead.
*/
public $properties = array();
/**
* @var GetterMetadata[]
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getPropertyMetadata()} instead.
*/
public $getters = array();
/**
* @var array
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getGroupSequence()} instead.
*/
public $groupSequence = array();
/**
* @var Boolean
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link isGroupSequenceProvider()} instead.
*/
public $groupSequenceProvider = false;
@ -70,6 +100,10 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
* By default, only instances of {@link \Traversable} are traversed.
*
* @var integer
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getTraversalStrategy()} instead.
*/
public $traversalStrategy = TraversalStrategy::IMPLICIT;
@ -94,6 +128,11 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
}
/**
* {@inheritdoc}
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
*/
public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
{
if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group
@ -129,9 +168,7 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
/**
* Returns the properties to be serialized
*
* @return array
* {@inheritdoc}
*/
public function __sleep()
{
@ -152,9 +189,7 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
/**
* Returns the fully qualified name of the class
*
* @return string The fully qualified class name
* {@inheritdoc}
*/
public function getClassName()
{
@ -356,9 +391,7 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
/**
* Returns all properties for which constraints are defined.
*
* @return array An array of property names
* {@inheritdoc}
*/
public function getConstrainedProperties()
{
@ -398,9 +431,7 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
/**
* Returns whether this class has an overridden default group sequence.
*
* @return Boolean
* {@inheritdoc}
*/
public function hasGroupSequence()
{
@ -408,9 +439,7 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
/**
* Returns the default group sequence for this class.
*
* @return GroupSequence The group sequence or null
* {@inheritdoc}
*/
public function getGroupSequence()
{
@ -452,9 +481,7 @@ class ClassMetadata extends ElementMetadata implements LegacyMetadataInterface,
}
/**
* Returns whether the class is a group sequence provider.
*
* @return Boolean
* {@inheritdoc}
*/
public function isGroupSequenceProvider()
{

View File

@ -17,7 +17,22 @@ use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
/**
* A factory for creating metadata for PHP classes.
* Creates new {@link ClassMetadataInterface} instances.
*
* Whenever {@link getMetadataFor()} is called for the first time with a given
* class name or object of that class, a new metadata instance is created and
* returned. On subsequent requests for the same class, the same metadata
* instance will be returned.
*
* You can optionally pass a {@link LoaderInterface} instance to the constructor.
* Whenever a new metadata instance, it will be passed to the loader, which can
* configure the metadata based on configuration loaded from the filesystem or
* a database. If you want to use multiple loaders, wrap them in a
* {@link Loader\LoaderChain}.
*
* You can also optionally pass a {@link CacheInterface} instance to the
* constructor. This cache will be used for persisting the generated metadata
* between multiple PHP requests.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
@ -25,18 +40,32 @@ class ClassMetadataFactory implements MetadataFactoryInterface
{
/**
* The loader for loading the class metadata
*
* @var LoaderInterface
*/
protected $loader;
/**
* The cache for caching class metadata
*
* @var CacheInterface
*/
protected $cache;
/**
* The loaded metadata, indexed by class name
*
* @var ClassMetadata[]
*/
protected $loadedClasses = array();
/**
* Creates a new metadata factory.
*
* @param LoaderInterface|null $loader The loader for configuring new metadata
* @param CacheInterface|null $cache The cache for persisting metadata
* between multiple PHP requests
*/
public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null)
{
$this->loader = $loader;
@ -44,7 +73,25 @@ class ClassMetadataFactory implements MetadataFactoryInterface
}
/**
* {@inheritdoc}
* Returns the metadata for the given class name or object.
*
* If the method was called with the same class name (or an object of that
* class) before, the same metadata instance is returned.
*
* If the factory was configured with a cache, this method will first look
* for an existing metadata instance in the cache. If an existing instance
* is found, it will be returned without further ado.
*
* Otherwise, a new metadata instance is created. If the factory was
* configured with a loader, the metadata is passed to the
* {@link LoaderInterface::loadClassMetadata()} method for further
* configuration. At last, the new object is returned.
*
* @param string|object $value A class name or an object
*
* @return MetadataInterface The metadata for the value
*
* @throws NoSuchMetadataException If no metadata exists for the given value
*/
public function getMetadataFor($value)
{
@ -93,7 +140,12 @@ class ClassMetadataFactory implements MetadataFactoryInterface
}
/**
* {@inheritdoc}
* Returns whether the factory is able to return metadata for the given
* class name or object.
*
* @param string|object $value A class name or an object
*
* @return Boolean Whether metadata can be returned for that class
*/
public function hasMetadataFor($value)
{

View File

@ -15,16 +15,66 @@ use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\PropertyMetadataContainerInterface as LegacyPropertyMetadataContainerInterface;;
/**
* @since %%NextVersion%%
* Stores all metadata needed for validating objects of specific class.
*
* Most importantly, the metadata stores the constraints against which an object
* and its properties should be validated.
*
* Additionally, the metadata stores whether the "Default" group is overridden
* by a group sequence for that class and whether instances of that class
* should be traversed or not.
*
* @since 2.5
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see MetadataInterface
* @see \Symfony\Component\Validator\Constraints\GroupSequence
* @see \Symfony\Component\Validator\GroupSequenceProviderInterface
* @see TraversalStrategy
*/
interface ClassMetadataInterface extends MetadataInterface, LegacyPropertyMetadataContainerInterface, ClassBasedInterface
{
/**
* Returns the names of all constrained properties.
*
* @return string[] A list of property names
*/
public function getConstrainedProperties();
/**
* Returns whether the "Default" group is overridden by a group sequence.
*
* If it is, you can access the group sequence with {@link getGroupSequence()}.
*
* @return Boolean Returns true if the "Default" group is overridden
*
* @see \Symfony\Component\Validator\Constraints\GroupSequence
*/
public function hasGroupSequence();
/**
* Returns the group sequence that overrides the "Default" group for this
* class.
*
* @return \Symfony\Component\Validator\Constraints\GroupSequence|null The group sequence or null
*
* @see \Symfony\Component\Validator\Constraints\GroupSequence
*/
public function getGroupSequence();
/**
* Returns whether the "Default" group is overridden by a dynamic group
* sequence obtained by the validated objects.
*
* If this method returns true, the class must implement
* {@link \Symfony\Component\Validator\GroupSequenceProviderInterface}.
* This interface will be used to obtain the group sequence when an object
* of this class is validated.
*
* @return Boolean Returns true if the "Default" group is overridden by
* a dynamic group sequence
*
* @see \Symfony\Component\Validator\GroupSequenceProviderInterface
*/
public function isGroupSequenceProvider();
}

View File

@ -11,6 +11,14 @@
namespace Symfony\Component\Validator\Mapping;
/**
* Contains the metadata of a structural element.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
* Extend {@link GenericMetadata} instead.
*/
abstract class ElementMetadata extends GenericMetadata
{
}

View File

@ -21,6 +21,8 @@ use Symfony\Component\Validator\ValidationVisitorInterface;
/**
* A generic container of {@link Constraint} objects.
*
* This class supports serialization and cloning.
*
* @since 2.5
* @author Bernhard Schussek <bschussek@gmail.com>
*/
@ -28,11 +30,19 @@ class GenericMetadata implements MetadataInterface
{
/**
* @var Constraint[]
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getConstraints()} and {@link findConstraints()} instead.
*/
public $constraints = array();
/**
* @var array
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link findConstraints()} instead.
*/
public $constraintsByGroup = array();
@ -44,6 +54,10 @@ class GenericMetadata implements MetadataInterface
* @var integer
*
* @see CascadingStrategy
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getCascadingStrategy()} instead.
*/
public $cascadingStrategy = CascadingStrategy::NONE;
@ -55,13 +69,17 @@ class GenericMetadata implements MetadataInterface
* @var integer
*
* @see TraversalStrategy
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getTraversalStrategy()} instead.
*/
public $traversalStrategy = TraversalStrategy::NONE;
/**
* Returns the names of the properties that should be serialized.
*
* @return array
* @return string[]
*/
public function __sleep()
{

View File

@ -13,6 +13,23 @@ namespace Symfony\Component\Validator\Mapping;
use Symfony\Component\Validator\Exception\ValidatorException;
/**
* Stores all metadata needed for validating a class property via its getter
* method.
*
* A property getter is any method that is equal to the property's name,
* prefixed with either "get" or "is". That method will be used to access the
* property's value.
*
* The getter will be invoked by reflection, so the access of private and
* protected getters is supported.
*
* This class supports serialization and cloning.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see PropertyMetadataInterface
*/
class GetterMetadata extends MemberMetadata
{
/**

View File

@ -16,11 +16,50 @@ use Symfony\Component\Validator\ValidationVisitorInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
/**
* Stores all metadata needed for validating a class property.
*
* The method of accessing the property's value must be specified by subclasses
* by implementing the {@link newReflectionMember()} method.
*
* This class supports serialization and cloning.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see PropertyMetadataInterface
*/
abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface
{
/**
* @var string
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getClassName()} instead.
*/
public $class;
/**
* @var string
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getName()} instead.
*/
public $name;
/**
* @var string
*
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getPropertyName()} instead.
*/
public $property;
/**
* @var \ReflectionMethod[]|\ReflectionProperty[]
*/
private $reflMember = array();
/**
@ -37,6 +76,11 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
$this->property = $property;
}
/**
* {@inheritdoc}
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
*/
public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
{
$visitor->visit($this, $value, $group, $propertyPath);
@ -64,9 +108,7 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns the names of the properties that should be serialized
*
* @return array
* {@inheritdoc}
*/
public function __sleep()
{
@ -78,7 +120,7 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns the name of the member
* Returns the name of the member.
*
* @return string
*/
@ -88,9 +130,7 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns the class this member is defined on
*
* @return string
* {@inheritdoc}
*/
public function getClassName()
{
@ -98,9 +138,7 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns the name of the property this member belongs to
*
* @return string The property name
* {@inheritdoc}
*/
public function getPropertyName()
{
@ -108,7 +146,7 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns whether this member is public
* Returns whether this member is public.
*
* @param object|string $objectOrClassName The object or the class name
*
@ -132,7 +170,7 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns whether this member is private
* Returns whether this member is private.
*
* @param object|string $objectOrClassName The object or the class name
*
@ -144,9 +182,12 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns whether objects stored in this member should be validated
* Returns whether objects stored in this member should be validated.
*
* @return Boolean
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
* Use {@link getCascadingStrategy()} instead.
*/
public function isCascaded()
{
@ -155,9 +196,12 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
/**
* Returns whether arrays or traversable objects stored in this member
* should be traversed and validated in each entry
* should be traversed and validated in each entry.
*
* @return Boolean
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
* Use {@link getTraversalStrategy()} instead.
*/
public function isCollectionCascaded()
{
@ -166,9 +210,12 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
/**
* Returns whether arrays or traversable objects stored in this member
* should be traversed recursively for inner arrays/traversable objects
* should be traversed recursively for inner arrays/traversable objects.
*
* @return Boolean
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
* Use {@link getTraversalStrategy()} instead.
*/
public function isCollectionCascadedDeeply()
{
@ -176,11 +223,11 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Returns the Reflection instance of the member
* Returns the reflection instance for accessing the member's value.
*
* @param object|string $objectOrClassName The object or the class name
*
* @return object
* @return \ReflectionMethod|\ReflectionProperty The reflection instance
*/
public function getReflectionMember($objectOrClassName)
{
@ -193,11 +240,13 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat
}
/**
* Creates a new Reflection instance for the member
* Creates a new reflection instance for accessing the member's value.
*
* Must be implemented by subclasses.
*
* @param object|string $objectOrClassName The object or the class name
*
* @return mixed Reflection class
* @return \ReflectionMethod|\ReflectionProperty The reflection instance
*/
abstract protected function newReflectionMember($objectOrClassName);
}

View File

@ -16,37 +16,36 @@ use Symfony\Component\Validator\MetadataInterface as LegacyMetadataInterface;
/**
* A container for validation metadata.
*
* The container contains constraints that may belong to different validation
* groups. Constraints for a specific group can be fetched by calling
* {@link findConstraints}.
* Most importantly, the metadata stores the constraints against which an object
* and its properties should be validated.
*
* Implement this interface to add validation metadata to your own metadata
* layer. Each metadata may have named properties. Each property can be
* represented by one or more {@link PropertyMetadataInterface} instances that
* are returned by {@link getPropertyMetadata}. Since
* <tt>PropertyMetadataInterface</tt> inherits from <tt>MetadataInterface</tt>,
* each property may be divided into further properties.
*
* The {@link accept} method of each metadata implements the Visitor pattern.
* The method should forward the call to the visitor's
* {@link ValidationVisitorInterface::visit} method and additionally call
* <tt>accept()</tt> on all structurally related metadata instances.
*
* For example, to store constraints for PHP classes and their properties,
* create a class <tt>ClassMetadata</tt> (implementing <tt>MetadataInterface</tt>)
* and a class <tt>PropertyMetadata</tt> (implementing <tt>PropertyMetadataInterface</tt>).
* <tt>ClassMetadata::getPropertyMetadata($property)</tt> returns all
* <tt>PropertyMetadata</tt> instances for a property of that class. Its
* <tt>accept()</tt>-method simply forwards to <tt>ValidationVisitorInterface::visit()</tt>
* and calls <tt>accept()</tt> on all contained <tt>PropertyMetadata</tt>
* instances, which themselves call <tt>ValidationVisitorInterface::visit()</tt>
* again.
* Additionally, the metadata stores whether objects should be validated
* against their class' metadata and whether traversable objects should be
* traversed or not.
*
* @since 2.5
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see CascadingStrategy
* @see TraversalStrategy
*/
interface MetadataInterface extends LegacyMetadataInterface
{
/**
* Returns the strategy for cascading objects.
*
* @return integer The cascading strategy
*
* @see CascadingStrategy
*/
public function getCascadingStrategy();
/**
* Returns the strategy for traversing traversable objects.
*
* @return integer The traversal strategy
*
* @see TraversalStrategy
*/
public function getTraversalStrategy();
}

View File

@ -13,6 +13,19 @@ namespace Symfony\Component\Validator\Mapping;
use Symfony\Component\Validator\Exception\ValidatorException;
/**
* Stores all metadata needed for validating a class property.
*
* The value of the property is obtained by directly accessing the property.
* The property will be accessed by reflection, so the access of private and
* protected properties is supported.
*
* This class supports serialization and cloning.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see PropertyMetadataInterface
*/
class PropertyMetadata extends MemberMetadata
{
/**

View File

@ -15,17 +15,21 @@ use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\PropertyMetadataInterface as LegacyPropertyMetadataInterface;
/**
* A container for validation metadata of a property.
* Stores all metadata needed for validating the value of a class property.
*
* What exactly you define as "property" is up to you. The validator expects
* implementations of {@link MetadataInterface} that contain constraints and
* optionally a list of named properties that also have constraints (and may
* have further sub properties). Such properties are mapped by implementations
* of this interface.
* Most importantly, the metadata stores the constraints against which the
* property's value should be validated.
*
* Additionally, the metadata stores whether objects stored in the property
* should be validated against their class' metadata and whether traversable
* objects should be traversed or not.
*
* @since 2.5
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see MetadataInterface
* @see CascadingStrategy
* @see TraversalStrategy
*/
interface PropertyMetadataInterface extends MetadataInterface, LegacyPropertyMetadataInterface, ClassBasedInterface
{

View File

@ -21,20 +21,20 @@ interface MetadataFactoryInterface
/**
* Returns the metadata for the given value.
*
* @param mixed $value Some value.
* @param mixed $value Some value
*
* @return MetadataInterface The metadata for the value.
* @return MetadataInterface The metadata for the value
*
* @throws Exception\NoSuchMetadataException If no metadata exists for the value.
* @throws Exception\NoSuchMetadataException If no metadata exists for the given value
*/
public function getMetadataFor($value);
/**
* Returns whether metadata exists for the given value.
* Returns whether the class is able to return metadata for the given value.
*
* @param mixed $value Some value.
* @param mixed $value Some value
*
* @return Boolean Whether metadata exists for the value.
* @return Boolean Whether metadata can be returned for that value
*/
public function hasMetadataFor($value);
}

View File

@ -53,10 +53,10 @@ interface MetadataInterface
* Calls {@link ValidationVisitorInterface::visit} and then forwards the
* <tt>accept()</tt>-call to all property metadata instances.
*
* @param ValidationVisitorInterface $visitor The visitor implementing the validation logic.
* @param mixed $value The value to validate.
* @param string|string[] $group The validation group to validate in.
* @param string $propertyPath The current property path in the validation graph.
* @param ValidationVisitorInterface $visitor The visitor implementing the validation logic
* @param mixed $value The value to validate
* @param string|string[] $group The validation group to validate in
* @param string $propertyPath The current property path in the validation graph
*
* @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0.
*/
@ -65,9 +65,9 @@ interface MetadataInterface
/**
* Returns all constraints for a given validation group.
*
* @param string $group The validation group.
* @param string $group The validation group
*
* @return Constraint[] A list of constraint instances.
* @return Constraint[] A list of constraint instances
*/
public function findConstraints($group);
}