Вход Регистрация
Файл: symfony-2.7/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
Строк: 642
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentValidatorMapping;

use 
SymfonyComponentValidatorConstraint;
use 
SymfonyComponentValidatorConstraintsGroupSequence;
use 
SymfonyComponentValidatorConstraintsTraverse;
use 
SymfonyComponentValidatorConstraintsValid;
use 
SymfonyComponentValidatorExceptionConstraintDefinitionException;
use 
SymfonyComponentValidatorExceptionGroupDefinitionException;
use 
SymfonyComponentValidatorValidationVisitorInterface;

/**
 * Default implementation of {@link ClassMetadataInterface}.
 *
 * This class supports serialization and cloning.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClassMetadata extends ElementMetadata implements ClassMetadataInterface
{
    
/**
     * @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 bool
     *
     * @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;

    
/**
     * The strategy for traversing traversable objects.
     *
     * By default, only instances of {@link Traversable} are traversed.
     *
     * @var int
     *
     * @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;

    
/**
     * @var ReflectionClass
     */
    
private $reflClass;

    
/**
     * Constructs a metadata for the given class.
     *
     * @param string $class
     */
    
public function __construct($class)
    {
        
$this->name $class;
        
// class name without namespace
        
if (false !== $nsSep strrpos($class'\')) {
            $this->defaultGroup = substr($class, $nsSep + 1);
        } else {
            $this->defaultGroup = $class;
        }
    }

    /**
     * {@inheritdoc}
     *
     * @deprecated since version 2.5, to be removed in 3.0.
     */
    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
    {
        trigger_error('
The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);

        if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group
                && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) {
            if ($this->hasGroupSequence()) {
                $groups = $this->getGroupSequence()->groups;
            } else {
                $groups = $value->getGroupSequence();
            }

            foreach ($groups as $group) {
                $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP);

                if (count($visitor->getViolations()) > 0) {
                    break;
                }
            }

            return;
        }

        $visitor->visit($this, $value, $group, $propertyPath);

        if (null !== $value) {
            $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'
.';

            foreach ($this->getConstrainedProperties() as $property) {
                foreach ($this->getPropertyMetadata($property) as $member) {
                    $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup);
                }
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function __sleep()
    {
        $parentProperties = parent::__sleep();

        // Don'
t store the cascading strategyClasses never cascade.
        unset(
$parentProperties[array_search('cascadingStrategy'$parentProperties)]);

        return 
array_merge($parentProperties, array(
            
'getters',
            
'groupSequence',
            
'groupSequenceProvider',
            
'members',
            
'name',
            
'properties',
            
'defaultGroup',
        ));
    }

    
/**
     * {@inheritdoc}
     */
    
public function getClassName()
    {
        return 
$this->name;
    }

    
/**
     * Returns the name of the default group for this class.
     *
     * For each class, the group "Default" is an alias for the group
     * "<ClassName>", where <ClassName> is the non-namespaced name of the
     * class. All constraints implicitly or explicitly assigned to group
     * "Default" belong to both of these groups, unless the class defines
     * a group sequence.
     *
     * If a class defines a group sequence, validating the class in "Default"
     * will validate the group sequence. The constraints assigned to "Default"
     * can still be validated by validating the class in "<ClassName>".
     *
     * @return string The name of the default group
     */
    
public function getDefaultGroup()
    {
        return 
$this->defaultGroup;
    }

    
/**
     * {@inheritdoc}
     */
    
public function addConstraint(Constraint $constraint)
    {
        if (!
in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) {
            throw new 
ConstraintDefinitionException(sprintf(
                
'The constraint "%s" cannot be put on classes.',
                
get_class($constraint)
            ));
        }

        if (
$constraint instanceof Valid) {
            throw new 
ConstraintDefinitionException(sprintf(
                
'The constraint "%s" cannot be put on classes.',
                
get_class($constraint)
            ));
        }

        if (
$constraint instanceof Traverse) {
            if (
$constraint->traverse) {
                
// If traverse is true, traversal should be explicitly enabled
                
$this->traversalStrategy TraversalStrategy::TRAVERSE;
            } else {
                
// If traverse is false, traversal should be explicitly disabled
                
$this->traversalStrategy TraversalStrategy::NONE;
            }

            
// The constraint is not added
            
return $this;
        }

        
$constraint->addImplicitGroupName($this->getDefaultGroup());

        
parent::addConstraint($constraint);

        return 
$this;
    }

    
/**
     * Adds a constraint to the given property.
     *
     * @param string     $property   The name of the property
     * @param Constraint $constraint The constraint
     *
     * @return ClassMetadata This object
     */
    
public function addPropertyConstraint($propertyConstraint $constraint)
    {
        if (!isset(
$this->properties[$property])) {
            
$this->properties[$property] = new PropertyMetadata($this->getClassName(), $property);

            
$this->addPropertyMetadata($this->properties[$property]);
        }

        
$constraint->addImplicitGroupName($this->getDefaultGroup());

        
$this->properties[$property]->addConstraint($constraint);

        return 
$this;
    }

    
/**
     * @param string       $property
     * @param Constraint[] $constraints
     *
     * @return ClassMetadata
     */
    
public function addPropertyConstraints($property, array $constraints)
    {
        foreach (
$constraints as $constraint) {
            
$this->addPropertyConstraint($property$constraint);
        }

        return 
$this;
    }

    
/**
     * Adds a constraint to the getter of the given property.
     *
     * The name of the getter is assumed to be the name of the property with an
     * uppercased first letter and either the prefix "get" or "is".
     *
     * @param string     $property   The name of the property
     * @param Constraint $constraint The constraint
     *
     * @return ClassMetadata This object
     */
    
public function addGetterConstraint($propertyConstraint $constraint)
    {
        if (!isset(
$this->getters[$property])) {
            
$this->getters[$property] = new GetterMetadata($this->getClassName(), $property);

            
$this->addPropertyMetadata($this->getters[$property]);
        }

        
$constraint->addImplicitGroupName($this->getDefaultGroup());

        
$this->getters[$property]->addConstraint($constraint);

        return 
$this;
    }

    
/**
     * @param string       $property
     * @param Constraint[] $constraints
     *
     * @return ClassMetadata
     */
    
public function addGetterConstraints($property, array $constraints)
    {
        foreach (
$constraints as $constraint) {
            
$this->addGetterConstraint($property$constraint);
        }

        return 
$this;
    }

    
/**
     * Merges the constraints of the given metadata into this object.
     *
     * @param ClassMetadata $source The source metadata
     */
    
public function mergeConstraints(ClassMetadata $source)
    {
        foreach (
$source->getConstraints() as $constraint) {
            
$this->addConstraint(clone $constraint);
        }

        foreach (
$source->getConstrainedProperties() as $property) {
            foreach (
$source->getPropertyMetadata($property) as $member) {
                
$member = clone $member;

                foreach (
$member->getConstraints() as $constraint) {
                    
$constraint->addImplicitGroupName($this->getDefaultGroup());
                }

                
$this->addPropertyMetadata($member);

                if (
$member instanceof MemberMetadata && !$member->isPrivate($this->name)) {
                    
$property $member->getPropertyName();

                    if (
$member instanceof PropertyMetadata && !isset($this->properties[$property])) {
                        
$this->properties[$property] = $member;
                    } elseif (
$member instanceof GetterMetadata && !isset($this->getters[$property])) {
                        
$this->getters[$property] = $member;
                    }
                }
            }
        }
    }

    
/**
     * Adds a member metadata.
     *
     * @param MemberMetadata $metadata
     *
     * @deprecated since version 2.6, to be removed in 3.0.
     */
    
protected function addMemberMetadata(MemberMetadata $metadata)
    {
        
trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the addPropertyMetadata() method instead.'E_USER_DEPRECATED);

        
$this->addPropertyMetadata($metadata);
    }

    
/**
     * Returns true if metadatas of members is present for the given property.
     *
     * @param string $property The name of the property
     *
     * @return bool
     *
     * @deprecated since version 2.6, to be removed in 3.0. Use {@link hasPropertyMetadata} instead.
     */
    
public function hasMemberMetadatas($property)
    {
        
trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the hasPropertyMetadata() method instead.'E_USER_DEPRECATED);

        return 
$this->hasPropertyMetadata($property);
    }

    
/**
     * Returns all metadatas of members describing the given property.
     *
     * @param string $property The name of the property
     *
     * @return MemberMetadata[] An array of MemberMetadata
     *
     * @deprecated since version 2.6, to be removed in 3.0. Use {@link getPropertyMetadata} instead.
     */
    
public function getMemberMetadatas($property)
    {
        
trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the getPropertyMetadata() method instead.'E_USER_DEPRECATED);

        return 
$this->getPropertyMetadata($property);
    }

    
/**
     * {@inheritdoc}
     */
    
public function hasPropertyMetadata($property)
    {
        return 
array_key_exists($property$this->members);
    }

    
/**
     * {@inheritdoc}
     */
    
public function getPropertyMetadata($property)
    {
        if (!isset(
$this->members[$property])) {
            return array();
        }

        return 
$this->members[$property];
    }

    
/**
     * {@inheritdoc}
     */
    
public function getConstrainedProperties()
    {
        return 
array_keys($this->members);
    }

    
/**
     * Sets the default group sequence for this class.
     *
     * @param array $groupSequence An array of group names
     *
     * @return ClassMetadata
     *
     * @throws GroupDefinitionException
     */
    
public function setGroupSequence($groupSequence)
    {
        if (
$this->isGroupSequenceProvider()) {
            throw new 
GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider');
        }

        if (
is_array($groupSequence)) {
            
$groupSequence = new GroupSequence($groupSequence);
        }

        if (
in_array(Constraint::DEFAULT_GROUP$groupSequence->groupstrue)) {
            throw new 
GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences'Constraint::DEFAULT_GROUP));
        }

        if (!
in_array($this->getDefaultGroup(), $groupSequence->groupstrue)) {
            throw new 
GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence'$this->getDefaultGroup()));
        }

        
$this->groupSequence $groupSequence;

        return 
$this;
    }

    
/**
     * {@inheritdoc}
     */
    
public function hasGroupSequence()
    {
        return 
$this->groupSequence && count($this->groupSequence->groups) > 0;
    }

    
/**
     * {@inheritdoc}
     */
    
public function getGroupSequence()
    {
        return 
$this->groupSequence;
    }

    
/**
     * Returns a ReflectionClass instance for this class.
     *
     * @return ReflectionClass
     */
    
public function getReflectionClass()
    {
        if (!
$this->reflClass) {
            
$this->reflClass = new ReflectionClass($this->getClassName());
        }

        return 
$this->reflClass;
    }

    
/**
     * Sets whether a group sequence provider should be used.
     *
     * @param bool $active
     *
     * @throws GroupDefinitionException
     */
    
public function setGroupSequenceProvider($active)
    {
        if (
$this->hasGroupSequence()) {
            throw new 
GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence');
        }

        if (!
$this->getReflectionClass()->implementsInterface('SymfonyComponentValidatorGroupSequenceProviderInterface')) {
            throw new 
GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface'$this->name));
        }

        
$this->groupSequenceProvider $active;
    }

    
/**
     * {@inheritdoc}
     */
    
public function isGroupSequenceProvider()
    {
        return 
$this->groupSequenceProvider;
    }

    
/**
     * Class nodes are never cascaded.
     *
     * {@inheritdoc}
     */
    
public function getCascadingStrategy()
    {
        return 
CascadingStrategy::NONE;
    }

    
/**
     * Adds a property metadata.
     *
     * @param PropertyMetadataInterface $metadata
     */
    
private function addPropertyMetadata(PropertyMetadataInterface $metadata)
    {
        
$property $metadata->getPropertyName();

        
$this->members[$property][] = $metadata;
    }
}
Онлайн: 2
Реклама