Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK! 9,DoctrineOrmExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\PropertyAccess\PropertyAccess; class DoctrineOrmExtension extends AbstractExtension { protected $registry; public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } protected function loadTypes() { return array( new Type\EntityType($this->registry, PropertyAccess::createPropertyAccessor()), ); } protected function loadTypeGuesser() { return new DoctrineOrmTypeGuesser($this->registry); } } PK!01EventListener/MergeDoctrineCollectionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\EventListener; use Doctrine\Common\Collections\Collection; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Merge changes from the request to a Doctrine\Common\Collections\Collection instance. * * This works with ORM, MongoDB and CouchDB instances of the collection interface. * * @author Bernhard Schussek * * @see Doctrine\Common\Collections\Collection */ class MergeDoctrineCollectionListener implements EventSubscriberInterface { public static function getSubscribedEvents() { // Higher priority than core MergeCollectionListener so that this one // is called before return array(FormEvents::SUBMIT => array('onBind', 10)); } public function onBind(FormEvent $event) { $collection = $event->getForm()->getData(); $data = $event->getData(); // If all items were removed, call clear which has a higher // performance on persistent collections if ($collection instanceof Collection && count($data) === 0) { $collection->clear(); } } } PK!!%d==$ChoiceList/EntityLoaderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\ChoiceList; /** * Custom loader for entities in the choice list. * * @author Benjamin Eberlei */ interface EntityLoaderInterface { /** * Returns an array of entities that are valid choices in the corresponding choice list. * * @return array The entities. */ public function getEntities(); /** * Returns an array of entities matching the given identifiers. * * @param string $identifier The identifier field of the object. This method * is not applicable for fields with multiple * identifiers. * @param array $values The values of the identifiers. * * @return array The entities. */ public function getEntitiesByIds($identifier, array $values); } PK! ?x77ChoiceList/EntityChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\ChoiceList; use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\StringCastException; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A choice list presenting a list of Doctrine entities as choices * * @author Bernhard Schussek */ class EntityChoiceList extends ObjectChoiceList { /** * @var ObjectManager */ private $em; /** * @var string */ private $class; /** * @var \Doctrine\Common\Persistence\Mapping\ClassMetadata */ private $classMetadata; /** * Contains the query builder that builds the query for fetching the * entities * * This property should only be accessed through queryBuilder. * * @var EntityLoaderInterface */ private $entityLoader; /** * The identifier field, if the identifier is not composite * * @var array */ private $idField = null; /** * Whether to use the identifier for index generation * * @var Boolean */ private $idAsIndex = false; /** * Whether to use the identifier for value generation * * @var Boolean */ private $idAsValue = false; /** * Whether the entities have already been loaded. * * @var Boolean */ private $loaded = false; /** * The preferred entities. * * @var array */ private $preferredEntities = array(); /** * Creates a new entity choice list. * * @param ObjectManager $manager An EntityManager instance * @param string $class The class name * @param string $labelPath The property path used for the label * @param EntityLoaderInterface $entityLoader An optional query builder * @param array $entities An array of choices * @param array $preferredEntities An array of preferred choices * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. */ public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null, PropertyAccessorInterface $propertyAccessor = null) { $this->em = $manager; $this->entityLoader = $entityLoader; $this->classMetadata = $manager->getClassMetadata($class); $this->class = $this->classMetadata->getName(); $this->loaded = is_array($entities) || $entities instanceof \Traversable; $this->preferredEntities = $preferredEntities; $identifier = $this->classMetadata->getIdentifierFieldNames(); if (1 === count($identifier)) { $this->idField = $identifier[0]; $this->idAsValue = true; if (in_array($this->classMetadata->getTypeOfField($this->idField), array('integer', 'smallint', 'bigint'))) { $this->idAsIndex = true; } } if (!$this->loaded) { // Make sure the constraints of the parent constructor are // fulfilled $entities = array(); } parent::__construct($entities, $labelPath, $preferredEntities, $groupPath, null, $propertyAccessor); } /** * Returns the list of entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getChoices() { if (!$this->loaded) { $this->load(); } return parent::getChoices(); } /** * Returns the values for the entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getValues() { if (!$this->loaded) { $this->load(); } return parent::getValues(); } /** * Returns the choice views of the preferred choices as nested array with * the choice groups as top-level keys. * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getPreferredViews() { if (!$this->loaded) { $this->load(); } return parent::getPreferredViews(); } /** * Returns the choice views of the choices that are not preferred as nested * array with the choice groups as top-level keys. * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getRemainingViews() { if (!$this->loaded) { $this->load(); } return parent::getRemainingViews(); } /** * Returns the entities corresponding to the given values. * * @param array $values * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getChoicesForValues(array $values) { // Performance optimization // Also prevents the generation of "WHERE id IN ()" queries through the // entity loader. At least with MySQL and on the development machine // this was tested on, no exception was thrown for such invalid // statements, consequently no test fails when this code is removed. // https://github.com/symfony/symfony/pull/8981#issuecomment-24230557 if (empty($values)) { return array(); } if (!$this->loaded) { // Optimize performance in case we have an entity loader and // a single-field identifier if ($this->idAsValue && $this->entityLoader) { $unorderedEntities = $this->entityLoader->getEntitiesByIds($this->idField, $values); $entitiesByValue = array(); $entities = array(); // Maintain order and indices from the given $values // An alternative approach to the following loop is to add the // "INDEX BY" clause to the Doctrine query in the loader, // but I'm not sure whether that's doable in a generic fashion. foreach ($unorderedEntities as $entity) { $value = $this->fixValue(current($this->getIdentifierValues($entity))); $entitiesByValue[$value] = $entity; } foreach ($values as $i => $value) { if (isset($entitiesByValue[$value])) { $entities[$i] = $entitiesByValue[$value]; } } return $entities; } $this->load(); } return parent::getChoicesForValues($values); } /** * Returns the values corresponding to the given entities. * * @param array $entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ public function getValuesForChoices(array $entities) { // Performance optimization if (empty($entities)) { return array(); } if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as values // Attention: This optimization does not check choices for existence if ($this->idAsValue) { $values = array(); foreach ($entities as $i => $entity) { if ($entity instanceof $this->class) { // Make sure to convert to the right format $values[$i] = $this->fixValue(current($this->getIdentifierValues($entity))); } } return $values; } $this->load(); } return parent::getValuesForChoices($entities); } /** * Returns the indices corresponding to the given entities. * * @param array $entities * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $entities) { // Performance optimization if (empty($entities)) { return array(); } if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as indices // Attention: This optimization does not check choices for existence if ($this->idAsIndex) { $indices = array(); foreach ($entities as $i => $entity) { if ($entity instanceof $this->class) { // Make sure to convert to the right format $indices[$i] = $this->fixIndex(current($this->getIdentifierValues($entity))); } } return $indices; } $this->load(); } return parent::getIndicesForChoices($entities); } /** * Returns the entities corresponding to the given values. * * @param array $values * * @return array * * @see Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { // Performance optimization if (empty($values)) { return array(); } if (!$this->loaded) { // Optimize performance for single-field identifiers. // Attention: This optimization does not check values for existence if ($this->idAsIndex && $this->idAsValue) { return $this->fixIndices($values); } $this->load(); } return parent::getIndicesForValues($values); } /** * Creates a new unique index for this entity. * * If the entity has a single-field identifier, this identifier is used. * * Otherwise a new integer is generated. * * @param mixed $entity The choice to create an index for * * @return integer|string A unique index containing only ASCII letters, * digits and underscores. */ protected function createIndex($entity) { if ($this->idAsIndex) { return $this->fixIndex(current($this->getIdentifierValues($entity))); } return parent::createIndex($entity); } /** * Creates a new unique value for this entity. * * If the entity has a single-field identifier, this identifier is used. * * Otherwise a new integer is generated. * * @param mixed $entity The choice to create a value for * * @return integer|string A unique value without character limitations. */ protected function createValue($entity) { if ($this->idAsValue) { return (string) current($this->getIdentifierValues($entity)); } return parent::createValue($entity); } /** * {@inheritdoc} */ protected function fixIndex($index) { $index = parent::fixIndex($index); // If the ID is a single-field integer identifier, it is used as // index. Replace any leading minus by underscore to make it a valid // form name. if ($this->idAsIndex && $index < 0) { $index = strtr($index, '-', '_'); } return $index; } /** * Loads the list with entities. */ private function load() { if ($this->entityLoader) { $entities = $this->entityLoader->getEntities(); } else { $entities = $this->em->getRepository($this->class)->findAll(); } try { // The second parameter $labels is ignored by ObjectChoiceList parent::initialize($entities, array(), $this->preferredEntities); } catch (StringCastException $e) { throw new StringCastException(str_replace('argument $labelPath', 'option "property"', $e->getMessage()), null, $e); } $this->loaded = true; } /** * Returns the values of the identifier fields of an entity. * * Doctrine must know about this entity, that is, the entity must already * be persisted or added to the identity map before. Otherwise an * exception is thrown. * * @param object $entity The entity for which to get the identifier * * @return array The identifier values * * @throws RuntimeException If the entity does not exist in Doctrine's identity map */ private function getIdentifierValues($entity) { if (!$this->em->contains($entity)) { throw new RuntimeException( 'Entities passed to the choice field must be managed. Maybe ' . 'persist them in the entity manager?' ); } $this->em->initializeObject($entity); return $this->classMetadata->getIdentifierValues($entity); } } PK!GCt $ChoiceList/ORMQueryBuilderLoader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\ChoiceList; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Doctrine\ORM\QueryBuilder; use Doctrine\DBAL\Connection; use Doctrine\ORM\EntityManager; /** * Getting Entities through the ORM QueryBuilder */ class ORMQueryBuilderLoader implements EntityLoaderInterface { /** * Contains the query builder that builds the query for fetching the * entities * * This property should only be accessed through queryBuilder. * * @var QueryBuilder */ private $queryBuilder; /** * Construct an ORM Query Builder Loader * * @param QueryBuilder|\Closure $queryBuilder * @param EntityManager $manager * @param string $class * * @throws UnexpectedTypeException */ public function __construct($queryBuilder, $manager = null, $class = null) { // If a query builder was passed, it must be a closure or QueryBuilder // instance if (!($queryBuilder instanceof QueryBuilder || $queryBuilder instanceof \Closure)) { throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure'); } if ($queryBuilder instanceof \Closure) { if (!$manager instanceof EntityManager) { throw new UnexpectedTypeException($manager, 'Doctrine\ORM\EntityManager'); } $queryBuilder = $queryBuilder($manager->getRepository($class)); if (!$queryBuilder instanceof QueryBuilder) { throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder'); } } $this->queryBuilder = $queryBuilder; } /** * {@inheritDoc} */ public function getEntities() { return $this->queryBuilder->getQuery()->execute(); } /** * {@inheritDoc} */ public function getEntitiesByIds($identifier, array $values) { $qb = clone ($this->queryBuilder); $alias = current($qb->getRootAliases()); $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier; $where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter); // Guess type $entity = current($qb->getRootEntities()); $metadata = $qb->getEntityManager()->getClassMetadata($entity); if (in_array($metadata->getTypeOfField($identifier), array('integer', 'bigint', 'smallint'))) { $parameterType = Connection::PARAM_INT_ARRAY; } else { $parameterType = Connection::PARAM_STR_ARRAY; } return $qb->andWhere($where) ->getQuery() ->setParameter($parameter, $values, $parameterType) ->getResult(); } } PK!`. qppDoctrineOrmTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\ORM\Mapping\MappingException as LegacyMappingException; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; use Doctrine\Common\Util\ClassUtils; class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface { protected $registry; private $cache = array(); public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } /** * {@inheritDoc} */ public function guessType($class, $property) { if (!$ret = $this->getMetadata($class)) { return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } list($metadata, $name) = $ret; if ($metadata->hasAssociation($property)) { $multiple = $metadata->isCollectionValuedAssociation($property); $mapping = $metadata->getAssociationMapping($property); return new TypeGuess('entity', array('em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple), Guess::HIGH_CONFIDENCE); } switch ($metadata->getTypeOfField($property)) { case 'array': return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE); case 'boolean': return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE); case 'datetime': case 'vardatetime': case 'datetimetz': return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE); case 'date': return new TypeGuess('date', array(), Guess::HIGH_CONFIDENCE); case 'time': return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE); case 'decimal': case 'float': return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); case 'integer': case 'bigint': case 'smallint': return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); case 'string': return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); case 'text': return new TypeGuess('textarea', array(), Guess::MEDIUM_CONFIDENCE); default: return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } } /** * {@inheritDoc} */ public function guessRequired($class, $property) { $classMetadatas = $this->getMetadata($class); if (!$classMetadatas) { return null; } /** @var ClassMetadataInfo $classMetadata */ $classMetadata = $classMetadatas[0]; // Check whether the field exists and is nullable or not if ($classMetadata->hasField($property)) { if (!$classMetadata->isNullable($property)) { return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE); } // Check whether the association exists, is a to-one association and its // join column is nullable or not if ($classMetadata->isAssociationWithSingleJoinColumn($property)) { $mapping = $classMetadata->getAssociationMapping($property); if (!isset($mapping['joinColumns'][0]['nullable'])) { // The "nullable" option defaults to true, in that case the // field should not be required. return new ValueGuess(false, Guess::HIGH_CONFIDENCE); } return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE); } return null; } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { $ret = $this->getMetadata($class); if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) { $mapping = $ret[0]->getFieldMapping($property); if (isset($mapping['length'])) { return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE); } if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } } /** * {@inheritDoc} */ public function guessPattern($class, $property) { $ret = $this->getMetadata($class); if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) { if (in_array($ret[0]->getTypeOfField($property), array('decimal', 'float'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } } protected function getMetadata($class) { // normalize class name $class = ClassUtils::getRealClass(ltrim($class, '\\')); if (array_key_exists($class, $this->cache)) { return $this->cache[$class]; } $this->cache[$class] = null; foreach ($this->registry->getManagers() as $name => $em) { try { return $this->cache[$class] = array($em->getClassMetadata($class), $name); } catch (MappingException $e) { // not an entity or mapped super class } catch (LegacyMappingException $e) { // not an entity or mapped super class, using Doctrine ORM 2.2 } } } } PK!CiPP0DataTransformer/CollectionToArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\DataTransformerInterface; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection; /** * @author Bernhard Schussek */ class CollectionToArrayTransformer implements DataTransformerInterface { /** * Transforms a collection into an array. * * @param Collection $collection A collection of entities * * @return mixed An array of entities * * @throws TransformationFailedException */ public function transform($collection) { if (null === $collection) { return array(); } // For cases when the collection getter returns $collection->toArray() // in order to prevent modifications of the returned collection if (is_array($collection)) { return $collection; } if (!$collection instanceof Collection) { throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.'); } return $collection->toArray(); } /** * Transforms choice keys into entities. * * @param mixed $array An array of entities * * @return Collection A collection of entities */ public function reverseTransform($array) { if ('' === $array || null === $array) { $array = array(); } else { $array = (array) $array; } return new ArrayCollection($array); } } PK!憝Type/EntityType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\Type; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; class EntityType extends DoctrineType { /** * Return the default loader object. * * @param ObjectManager $manager * @param mixed $queryBuilder * @param string $class * @return ORMQueryBuilderLoader */ public function getLoader(ObjectManager $manager, $queryBuilder, $class) { return new ORMQueryBuilderLoader( $queryBuilder, $manager, $class ); } public function getName() { return 'entity'; } } PK!S;,:Type/DoctrineType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Doctrine\Form\Type; use Doctrine\Common\Persistence\ManagerRegistry; use Symfony\Component\Form\Exception\RuntimeException; use Doctrine\Common\Persistence\ObjectManager; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList; use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface; use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener; use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; abstract class DoctrineType extends AbstractType { /** * @var ManagerRegistry */ protected $registry; /** * @var array */ private $choiceListCache = array(); /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null) { $this->registry = $registry; $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } public function buildForm(FormBuilderInterface $builder, array $options) { if ($options['multiple']) { $builder ->addEventSubscriber(new MergeDoctrineCollectionListener()) ->addViewTransformer(new CollectionToArrayTransformer(), true) ; } } public function setDefaultOptions(OptionsResolverInterface $resolver) { $choiceListCache =& $this->choiceListCache; $registry = $this->registry; $propertyAccessor = $this->propertyAccessor; $type = $this; $loader = function (Options $options) use ($type) { if (null !== $options['query_builder']) { return $type->getLoader($options['em'], $options['query_builder'], $options['class']); } return null; }; $choiceList = function (Options $options) use (&$choiceListCache, $propertyAccessor) { // Support for closures $propertyHash = is_object($options['property']) ? spl_object_hash($options['property']) : $options['property']; $choiceHashes = $options['choices']; // Support for recursive arrays if (is_array($choiceHashes)) { // A second parameter ($key) is passed, so we cannot use // spl_object_hash() directly (which strictly requires // one parameter) array_walk_recursive($choiceHashes, function (&$value) { $value = spl_object_hash($value); }); } elseif ($choiceHashes instanceof \Traversable) { $hashes = array(); foreach ($choiceHashes as $value) { $hashes[] = spl_object_hash($value); } $choiceHashes = $hashes; } $preferredChoiceHashes = $options['preferred_choices']; if (is_array($preferredChoiceHashes)) { array_walk_recursive($preferredChoiceHashes, function (&$value) { $value = spl_object_hash($value); }); } // Support for custom loaders (with query builders) $loaderHash = is_object($options['loader']) ? spl_object_hash($options['loader']) : $options['loader']; // Support for closures $groupByHash = is_object($options['group_by']) ? spl_object_hash($options['group_by']) : $options['group_by']; $hash = hash('sha256', json_encode(array( spl_object_hash($options['em']), $options['class'], $propertyHash, $loaderHash, $choiceHashes, $preferredChoiceHashes, $groupByHash ))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new EntityChoiceList( $options['em'], $options['class'], $options['property'], $options['loader'], $options['choices'], $options['preferred_choices'], $options['group_by'], $propertyAccessor ); } return $choiceListCache[$hash]; }; $emNormalizer = function (Options $options, $em) use ($registry) { /* @var ManagerRegistry $registry */ if (null !== $em) { return $registry->getManager($em); } $em = $registry->getManagerForClass($options['class']); if (null === $em) { throw new RuntimeException(sprintf( 'Class "%s" seems not to be a managed Doctrine entity. ' . 'Did you forget to map it?', $options['class'] )); } return $em; }; $resolver->setDefaults(array( 'em' => null, 'property' => null, 'query_builder' => null, 'loader' => $loader, 'choices' => null, 'choice_list' => $choiceList, 'group_by' => null, )); $resolver->setRequired(array('class')); $resolver->setNormalizers(array( 'em' => $emNormalizer, )); $resolver->setAllowedTypes(array( 'loader' => array('null', 'Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface'), )); } /** * Return the default loader object. * * @param ObjectManager $manager * @param mixed $queryBuilder * @param string $class * * @return EntityLoaderInterface */ abstract public function getLoader(ObjectManager $manager, $queryBuilder, $class); public function getParent() { return 'choice'; } } PK!)..FormRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Renders a form into HTML using a rendering engine. * * @author Bernhard Schussek */ class FormRenderer implements FormRendererInterface { const CACHE_KEY_VAR = 'unique_block_prefix'; /** * @var FormRendererEngineInterface */ private $engine; /** * @var CsrfTokenManagerInterface */ private $csrfTokenManager; /** * @var array */ private $blockNameHierarchyMap = array(); /** * @var array */ private $hierarchyLevelMap = array(); /** * @var array */ private $variableStack = array(); /** * Constructor. * * @param FormRendererEngineInterface $engine * @param CsrfTokenManagerInterface|null $csrfTokenManager * * @throws UnexpectedTypeException */ public function __construct(FormRendererEngineInterface $engine, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface or null'); } $this->engine = $engine; $this->csrfTokenManager = $csrfTokenManager; } /** * {@inheritdoc} */ public function getEngine() { return $this->engine; } /** * {@inheritdoc} */ public function setTheme(FormView $view, $themes) { $this->engine->setTheme($view, $themes); } /** * {@inheritdoc} */ public function renderCsrfToken($tokenId) { if (null === $this->csrfTokenManager) { throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct().'); } return $this->csrfTokenManager->getToken($tokenId)->getValue(); } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $blockName, array $variables = array()) { $resource = $this->engine->getResourceForBlockName($view, $blockName); if (!$resource) { throw new LogicException(sprintf('No block "%s" found while rendering the form.', $blockName)); } $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { $this->variableStack[$viewCacheKey] = array(); // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; $varInit = true; } else { // Reuse the current scope and merge it with the explicitly passed variables $scopeVariables = end($this->variableStack[$viewCacheKey]); $varInit = false; } // Merge the passed with the existing attributes if (isset($variables['attr']) && isset($scopeVariables['attr'])) { $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); } // Merge the passed with the exist *label* attributes if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); } // Do not use array_replace_recursive(), otherwise array variables // cannot be overwritten $variables = array_replace($scopeVariables, $variables); $this->variableStack[$viewCacheKey][] = $variables; // Do the rendering $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); // Clear the stack array_pop($this->variableStack[$viewCacheKey]); if ($varInit) { unset($this->variableStack[$viewCacheKey]); } return $html; } /** * {@inheritdoc} */ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array()) { $renderOnlyOnce = 'row' === $blockNameSuffix || 'widget' === $blockNameSuffix; if ($renderOnlyOnce && $view->isRendered()) { return ''; } // The cache key for storing the variables and types $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; $viewAndSuffixCacheKey = $viewCacheKey.$blockNameSuffix; // In templates, we have to deal with two kinds of block hierarchies: // // +---------+ +---------+ // | Theme B | -------> | Theme A | // +---------+ +---------+ // // form_widget -------> form_widget // ^ // | // choice_widget -----> choice_widget // // The first kind of hierarchy is the theme hierarchy. This allows to // override the block "choice_widget" from Theme A in the extending // Theme B. This kind of inheritance needs to be supported by the // template engine and, for example, offers "parent()" or similar // functions to fall back from the custom to the parent implementation. // // The second kind of hierarchy is the form type hierarchy. This allows // to implement a custom "choice_widget" block (no matter in which theme), // or to fallback to the block of the parent type, which would be // "form_widget" in this example (again, no matter in which theme). // If the designer wants to explicitly fallback to "form_widget" in his // custom "choice_widget", for example because he only wants to wrap // a
around the original implementation, he can simply call the // widget() function again to render the block for the parent type. // // The second kind is implemented in the following blocks. if (!isset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey])) { // INITIAL CALL // Calculate the hierarchy of template blocks and start on // the bottom level of the hierarchy (= "__
" block) $blockNameHierarchy = array(); foreach ($view->vars['block_prefixes'] as $blockNamePrefix) { $blockNameHierarchy[] = $blockNamePrefix.'_'.$blockNameSuffix; } $hierarchyLevel = count($blockNameHierarchy) - 1; $hierarchyInit = true; } else { // RECURSIVE CALL // If a block recursively calls searchAndRenderBlock() again, resume rendering // using the parent type in the hierarchy. $blockNameHierarchy = $this->blockNameHierarchyMap[$viewAndSuffixCacheKey]; $hierarchyLevel = $this->hierarchyLevelMap[$viewAndSuffixCacheKey] - 1; $hierarchyInit = false; } // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { $this->variableStack[$viewCacheKey] = array(); // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; $varInit = true; } else { // Reuse the current scope and merge it with the explicitly passed variables $scopeVariables = end($this->variableStack[$viewCacheKey]); $varInit = false; } // Load the resource where this block can be found $resource = $this->engine->getResourceForBlockNameHierarchy($view, $blockNameHierarchy, $hierarchyLevel); // Update the current hierarchy level to the one at which the resource was // found. For example, if looking for "choice_widget", but only a resource // is found for its parent "form_widget", then the level is updated here // to the parent level. $hierarchyLevel = $this->engine->getResourceHierarchyLevel($view, $blockNameHierarchy, $hierarchyLevel); // The actually existing block name in $resource $blockName = $blockNameHierarchy[$hierarchyLevel]; // Escape if no resource exists for this block if (!$resource) { throw new LogicException(sprintf( 'Unable to render the form as none of the following blocks exist: "%s".', implode('", "', array_reverse($blockNameHierarchy)) )); } // Merge the passed with the existing attributes if (isset($variables['attr']) && isset($scopeVariables['attr'])) { $variables['attr'] = array_replace($scopeVariables['attr'], $variables['attr']); } // Merge the passed with the exist *label* attributes if (isset($variables['label_attr']) && isset($scopeVariables['label_attr'])) { $variables['label_attr'] = array_replace($scopeVariables['label_attr'], $variables['label_attr']); } // Do not use array_replace_recursive(), otherwise array variables // cannot be overwritten $variables = array_replace($scopeVariables, $variables); // In order to make recursive calls possible, we need to store the block hierarchy, // the current level of the hierarchy and the variables so that this method can // resume rendering one level higher of the hierarchy when it is called recursively. // // We need to store these values in maps (associative arrays) because within a // call to widget() another call to widget() can be made, but for a different view // object. These nested calls should not override each other. $this->blockNameHierarchyMap[$viewAndSuffixCacheKey] = $blockNameHierarchy; $this->hierarchyLevelMap[$viewAndSuffixCacheKey] = $hierarchyLevel; // We also need to store the variables for the view so that we can render other // blocks for the same view using the same variables as in the outer block. $this->variableStack[$viewCacheKey][] = $variables; // Do the rendering $html = $this->engine->renderBlock($view, $resource, $blockName, $variables); // Clear the stack array_pop($this->variableStack[$viewCacheKey]); // Clear the caches if they were filled for the first time within // this function call if ($hierarchyInit) { unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey]); unset($this->hierarchyLevelMap[$viewAndSuffixCacheKey]); } if ($varInit) { unset($this->variableStack[$viewCacheKey]); } if ($renderOnlyOnce) { $view->setRendered(); } return $html; } /** * {@inheritdoc} */ public function humanize($text) { return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); } } PK!CButtonTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A type that should be converted into a {@link Button} instance. * * @author Bernhard Schussek */ interface ButtonTypeInterface extends FormTypeInterface { } PK!K'$FormBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * A builder for creating {@link Form} instances. * * @author Bernhard Schussek */ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface { /** * The children of the form builder. * * @var FormBuilderInterface[] */ private $children = array(); /** * The data of children who haven't been converted to form builders yet. * * @var array */ private $unresolvedChildren = array(); /** * Creates a new form builder. * * @param string $name * @param string $dataClass * @param EventDispatcherInterface $dispatcher * @param FormFactoryInterface $factory * @param array $options */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory, array $options = array()) { parent::__construct($name, $dataClass, $dispatcher, $options); $this->setFormFactory($factory); } /** * {@inheritdoc} */ public function add($child, $type = null, array $options = array()) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($child instanceof self) { $this->children[$child->getName()] = $child; // In case an unresolved child with the same name exists unset($this->unresolvedChildren[$child->getName()]); return $this; } if (!is_string($child) && !is_int($child)) { throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } // Add to "children" to maintain order $this->children[$child] = null; $this->unresolvedChildren[$child] = array( 'type' => $type, 'options' => $options, ); return $this; } /** * {@inheritdoc} */ public function create($name, $type = null, array $options = array()) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null === $type && null === $this->getDataClass()) { $type = 'text'; } if (null !== $type) { return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options); } return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options); } /** * {@inheritdoc} */ public function get($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (isset($this->unresolvedChildren[$name])) { return $this->resolveChild($name); } if (isset($this->children[$name])) { return $this->children[$name]; } throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name)); } /** * {@inheritdoc} */ public function remove($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } unset($this->unresolvedChildren[$name]); if (array_key_exists($name, $this->children)) { unset($this->children[$name]); } return $this; } /** * {@inheritdoc} */ public function has($name) { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (isset($this->unresolvedChildren[$name])) { return true; } if (isset($this->children[$name])) { return true; } return false; } /** * {@inheritdoc} */ public function all() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->resolveChildren(); return $this->children; } /** * {@inheritdoc} */ public function count() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return count($this->children); } /** * {@inheritdoc} */ public function getFormConfig() { $config = parent::getFormConfig(); $config->children = array(); $config->unresolvedChildren = array(); return $config; } /** * {@inheritdoc} */ public function getForm() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->resolveChildren(); $form = new Form($this->getFormConfig()); foreach ($this->children as $child) { // Automatic initialization is only supported on root forms $form->add($child->setAutoInitialize(false)->getForm()); } if ($this->getAutoInitialize()) { // Automatically initialize the form if it is configured so $form->initialize(); } return $form; } /** * {@inheritdoc} */ public function getIterator() { if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return new \ArrayIterator($this->children); } /** * Converts an unresolved child into a {@link FormBuilder} instance. * * @param string $name The name of the unresolved child. * * @return FormBuilder The created instance. */ private function resolveChild($name) { $info = $this->unresolvedChildren[$name]; $child = $this->create($name, $info['type'], $info['options']); $this->children[$name] = $child; unset($this->unresolvedChildren[$name]); return $child; } /** * Converts all unresolved children into {@link FormBuilder} instances. */ private function resolveChildren() { foreach ($this->unresolvedChildren as $name => $info) { $this->children[$name] = $this->create($name, $info['type'], $info['options']); } $this->unresolvedChildren = array(); } } PK!&"̰TTFormConfigBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; /** * A basic form configuration. * * @author Bernhard Schussek */ class FormConfigBuilder implements FormConfigBuilderInterface { /** * Caches a globally unique {@link NativeRequestHandler} instance. * * @var NativeRequestHandler */ private static $nativeRequestProcessor; /** * The accepted request methods. * * @var array */ private static $allowedMethods = array( 'GET', 'PUT', 'POST', 'DELETE', 'PATCH' ); /** * @var Boolean */ protected $locked = false; /** * @var EventDispatcherInterface */ private $dispatcher; /** * @var string */ private $name; /** * @var PropertyPathInterface */ private $propertyPath; /** * @var Boolean */ private $mapped = true; /** * @var Boolean */ private $byReference = true; /** * @var Boolean */ private $inheritData = false; /** * @var Boolean */ private $compound = false; /** * @var ResolvedFormTypeInterface */ private $type; /** * @var array */ private $viewTransformers = array(); /** * @var array */ private $modelTransformers = array(); /** * @var DataMapperInterface */ private $dataMapper; /** * @var Boolean */ private $required = true; /** * @var Boolean */ private $disabled = false; /** * @var Boolean */ private $errorBubbling = false; /** * @var mixed */ private $emptyData; /** * @var array */ private $attributes = array(); /** * @var mixed */ private $data; /** * @var string */ private $dataClass; /** * @var Boolean */ private $dataLocked; /** * @var FormFactoryInterface */ private $formFactory; /** * @var string */ private $action; /** * @var string */ private $method = 'POST'; /** * @var RequestHandlerInterface */ private $requestHandler; /** * @var Boolean */ private $autoInitialize = false; /** * @var array */ private $options; /** * Creates an empty form configuration. * * @param string|integer $name The form name * @param string $dataClass The class of the form's data * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options * * @throws InvalidArgumentException If the data class is not a valid class or if * the name contains invalid characters. */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) { self::validateName($name); if (null !== $dataClass && !class_exists($dataClass)) { throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); } $this->name = (string) $name; $this->dataClass = $dataClass; $this->dispatcher = $dispatcher; $this->options = $options; } /** * {@inheritdoc} */ public function addEventListener($eventName, $listener, $priority = 0) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addListener($eventName, $listener, $priority); return $this; } /** * {@inheritdoc} */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addSubscriber($subscriber); return $this; } /** * {@inheritdoc} */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forcePrepend) { array_unshift($this->viewTransformers, $viewTransformer); } else { $this->viewTransformers[] = $viewTransformer; } return $this; } /** * {@inheritdoc} */ public function resetViewTransformers() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->viewTransformers = array(); return $this; } /** * {@inheritdoc} */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forceAppend) { $this->modelTransformers[] = $modelTransformer; } else { array_unshift($this->modelTransformers, $modelTransformer); } return $this; } /** * {@inheritdoc} */ public function resetModelTransformers() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->modelTransformers = array(); return $this; } /** * {@inheritdoc} */ public function getEventDispatcher() { if ($this->locked && !$this->dispatcher instanceof ImmutableEventDispatcher) { $this->dispatcher = new ImmutableEventDispatcher($this->dispatcher); } return $this->dispatcher; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function getPropertyPath() { return $this->propertyPath; } /** * {@inheritdoc} */ public function getMapped() { return $this->mapped; } /** * {@inheritdoc} */ public function getByReference() { return $this->byReference; } /** * {@inheritdoc} */ public function getInheritData() { return $this->inheritData; } /** * Alias of {@link getInheritData()}. * * @return FormConfigBuilder The configuration object. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link getInheritData()} instead. */ public function getVirtual() { // Uncomment this as soon as the deprecation note should be shown // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED); return $this->getInheritData(); } /** * {@inheritdoc} */ public function getCompound() { return $this->compound; } /** * {@inheritdoc} */ public function getType() { return $this->type; } /** * {@inheritdoc} */ public function getViewTransformers() { return $this->viewTransformers; } /** * {@inheritdoc} */ public function getModelTransformers() { return $this->modelTransformers; } /** * {@inheritdoc} */ public function getDataMapper() { return $this->dataMapper; } /** * {@inheritdoc} */ public function getRequired() { return $this->required; } /** * {@inheritdoc} */ public function getDisabled() { return $this->disabled; } /** * {@inheritdoc} */ public function getErrorBubbling() { return $this->errorBubbling; } /** * {@inheritdoc} */ public function getEmptyData() { return $this->emptyData; } /** * {@inheritdoc} */ public function getAttributes() { return $this->attributes; } /** * {@inheritdoc} */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * {@inheritdoc} */ public function getAttribute($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * {@inheritdoc} */ public function getData() { return $this->data; } /** * {@inheritdoc} */ public function getDataClass() { return $this->dataClass; } /** * {@inheritdoc} */ public function getDataLocked() { return $this->dataLocked; } /** * {@inheritdoc} */ public function getFormFactory() { return $this->formFactory; } /** * {@inheritdoc} */ public function getAction() { return $this->action; } /** * {@inheritdoc} */ public function getMethod() { return $this->method; } /** * {@inheritdoc} */ public function getRequestHandler() { if (null === $this->requestHandler) { if (null === self::$nativeRequestProcessor) { self::$nativeRequestProcessor = new NativeRequestHandler(); } $this->requestHandler = self::$nativeRequestProcessor; } return $this->requestHandler; } /** * {@inheritdoc} */ public function getAutoInitialize() { return $this->autoInitialize; } /** * {@inheritdoc} */ public function getOptions() { return $this->options; } /** * {@inheritdoc} */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * {@inheritdoc} */ public function getOption($name, $default = null) { return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** * {@inheritdoc} */ public function setAttribute($name, $value) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes[$name] = $value; return $this; } /** * {@inheritdoc} */ public function setAttributes(array $attributes) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes = $attributes; return $this; } /** * {@inheritdoc} */ public function setDataMapper(DataMapperInterface $dataMapper = null) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataMapper = $dataMapper; return $this; } /** * {@inheritdoc} */ public function setDisabled($disabled) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->disabled = (Boolean) $disabled; return $this; } /** * {@inheritdoc} */ public function setEmptyData($emptyData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->emptyData = $emptyData; return $this; } /** * {@inheritdoc} */ public function setErrorBubbling($errorBubbling) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; return $this; } /** * {@inheritdoc} */ public function setRequired($required) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->required = (Boolean) $required; return $this; } /** * {@inheritdoc} */ public function setPropertyPath($propertyPath) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) { $propertyPath = new PropertyPath($propertyPath); } $this->propertyPath = $propertyPath; return $this; } /** * {@inheritdoc} */ public function setMapped($mapped) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->mapped = $mapped; return $this; } /** * {@inheritdoc} */ public function setByReference($byReference) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->byReference = $byReference; return $this; } /** * {@inheritdoc} */ public function setInheritData($inheritData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->inheritData = $inheritData; return $this; } /** * Alias of {@link setInheritData()}. * * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return FormConfigBuilder The configuration object. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link setInheritData()} instead. */ public function setVirtual($inheritData) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('setVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use setInheritData() instead.', E_USER_DEPRECATED); $this->setInheritData($inheritData); } /** * {@inheritdoc} */ public function setCompound($compound) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->compound = $compound; return $this; } /** * {@inheritdoc} */ public function setType(ResolvedFormTypeInterface $type) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->type = $type; return $this; } /** * {@inheritdoc} */ public function setData($data) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->data = $data; return $this; } /** * {@inheritdoc} */ public function setDataLocked($locked) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataLocked = $locked; return $this; } /** * {@inheritdoc} */ public function setFormFactory(FormFactoryInterface $formFactory) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->formFactory = $formFactory; return $this; } /** * {@inheritdoc} */ public function setAction($action) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $this->action = $action; return $this; } /** * {@inheritdoc} */ public function setMethod($method) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $upperCaseMethod = strtoupper($method); if (!in_array($upperCaseMethod, self::$allowedMethods)) { throw new InvalidArgumentException(sprintf( 'The form method is "%s", but should be one of "%s".', $method, implode('", "', self::$allowedMethods) )); } $this->method = $upperCaseMethod; return $this; } /** * {@inheritdoc} */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } $this->requestHandler = $requestHandler; return $this; } /** * {@inheritdoc} */ public function setAutoInitialize($initialize) { $this->autoInitialize = (Boolean) $initialize; return $this; } /** * {@inheritdoc} */ public function getFormConfig() { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; return $config; } /** * Validates whether the given variable is a valid form name. * * @param string|integer $name The tested form name. * * @throws UnexpectedTypeException If the name is not a string or an integer. * @throws InvalidArgumentException If the name contains invalid characters. */ public static function validateName($name) { if (null !== $name && !is_string($name) && !is_int($name)) { throw new UnexpectedTypeException($name, 'string, integer or null'); } if (!self::isValidName($name)) { throw new InvalidArgumentException(sprintf( 'The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").', $name )); } } /** * Returns whether the given variable contains a valid form name. * * A name is accepted if it * * * is empty * * starts with a letter, digit or underscore * * contains only letters, digits, numbers, underscores ("_"), * hyphens ("-") and colons (":") * * @param string $name The tested form name. * * @return Boolean Whether the name is valid. */ public static function isValidName($name) { return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); } } PK!E1'SubmitButtonTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A type that should be converted into a {@link SubmitButton} instance. * * @author Bernhard Schussek */ interface SubmitButtonTypeInterface extends FormTypeInterface { } PK!dFormRegistry.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\ExceptionInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * The central registry of the Form component. * * @author Bernhard Schussek */ class FormRegistry implements FormRegistryInterface { /** * Extensions * * @var FormExtensionInterface[] An array of FormExtensionInterface */ private $extensions = array(); /** * @var array */ private $types = array(); /** * @var FormTypeGuesserInterface|false|null */ private $guesser = false; /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; /** * Constructor. * * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types. * * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface */ public function __construct(array $extensions, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { foreach ($extensions as $extension) { if (!$extension instanceof FormExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormExtensionInterface'); } } $this->extensions = $extensions; $this->resolvedTypeFactory = $resolvedTypeFactory; } /** * {@inheritdoc} */ public function getType($name) { if (!is_string($name)) { throw new UnexpectedTypeException($name, 'string'); } if (!isset($this->types[$name])) { /** @var FormTypeInterface $type */ $type = null; foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ if ($extension->hasType($name)) { $type = $extension->getType($name); break; } } if (!$type) { throw new InvalidArgumentException(sprintf('Could not load type "%s"', $name)); } $this->resolveAndAddType($type); } return $this->types[$name]; } /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. * * @param FormTypeInterface $type The type to resolve. * * @return ResolvedFormTypeInterface The resolved type. */ private function resolveAndAddType(FormTypeInterface $type) { $parentType = $type->getParent(); if ($parentType instanceof FormTypeInterface) { $this->resolveAndAddType($parentType); $parentType = $parentType->getName(); } $typeExtensions = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $typeExtensions = array_merge( $typeExtensions, $extension->getTypeExtensions($type->getName()) ); } $this->types[$type->getName()] = $this->resolvedTypeFactory->createResolvedType( $type, $typeExtensions, $parentType ? $this->getType($parentType) : null ); } /** * {@inheritdoc} */ public function hasType($name) { if (isset($this->types[$name])) { return true; } try { $this->getType($name); } catch (ExceptionInterface $e) { return false; } return true; } /** * {@inheritdoc} */ public function getTypeGuesser() { if (false === $this->guesser) { $guessers = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $guesser = $extension->getTypeGuesser(); if ($guesser) { $guessers[] = $guesser; } } $this->guesser = !empty($guessers) ? new FormTypeGuesserChain($guessers) : null; } return $this->guesser; } /** * {@inheritdoc} */ public function getExtensions() { return $this->extensions; } } PK!ÊM'%%FormConfigInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The configuration of a {@link Form} object. * * @author Bernhard Schussek */ interface FormConfigInterface { /** * Returns the event dispatcher used to dispatch form events. * * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface The dispatcher. */ public function getEventDispatcher(); /** * Returns the name of the form used as HTTP parameter. * * @return string The form name. */ public function getName(); /** * Returns the property path that the form should be mapped to. * * @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); /** * Returns whether the form should be mapped to an element of its * parent's data. * * @return Boolean Whether the form is mapped. */ public function getMapped(); /** * Returns whether the form's data should be modified by reference. * * @return Boolean Whether to modify the form's data by reference. */ public function getByReference(); /** * Returns whether the form should read and write the data of its parent. * * @return Boolean Whether the form should inherit its parent's data. */ public function getInheritData(); /** * Returns whether the form is compound. * * This property is independent of whether the form actually has * children. A form can be compound and have no children at all, like * for example an empty collection form. * * @return Boolean Whether the form is compound. */ public function getCompound(); /** * Returns the form types used to construct the form. * * @return ResolvedFormTypeInterface The form's type. */ public function getType(); /** * Returns the view transformers of the form. * * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getViewTransformers(); /** * Returns the model transformers of the form. * * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getModelTransformers(); /** * Returns the data mapper of the form. * * @return DataMapperInterface The data mapper. */ public function getDataMapper(); /** * Returns whether the form is required. * * @return Boolean Whether the form is required. */ public function getRequired(); /** * Returns whether the form is disabled. * * @return Boolean Whether the form is disabled. */ public function getDisabled(); /** * Returns whether errors attached to the form will bubble to its parent. * * @return Boolean Whether errors will bubble up. */ public function getErrorBubbling(); /** * Returns the data that should be returned when the form is empty. * * @return mixed The data returned if the form is empty. */ public function getEmptyData(); /** * Returns additional attributes of the form. * * @return array An array of key-value combinations. */ public function getAttributes(); /** * Returns whether the attribute with the given name exists. * * @param string $name The attribute name. * * @return Boolean Whether the attribute exists. */ public function hasAttribute($name); /** * Returns the value of the given attribute. * * @param string $name The attribute name. * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ public function getAttribute($name, $default = null); /** * Returns the initial data of the form. * * @return mixed The initial form data. */ public function getData(); /** * Returns the class of the form data or null if the data is scalar or an array. * * @return string The data class or null. */ public function getDataClass(); /** * Returns whether the form's data is locked. * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by * submitting the form. * * @return Boolean Whether the data is locked. */ public function getDataLocked(); /** * Returns the form factory used for creating new forms. * * @return FormFactoryInterface The form factory. */ public function getFormFactory(); /** * Returns the target URL of the form. * * @return string The target URL of the form. */ public function getAction(); /** * Returns the HTTP method used by the form. * * @return string The HTTP method of the form. */ public function getMethod(); /** * Returns the request handler used by the form. * * @return RequestHandlerInterface The request handler. */ public function getRequestHandler(); /** * Returns whether the form should be initialized upon creation. * * @return Boolean Returns true if the form should be initialized * when created, false otherwise. */ public function getAutoInitialize(); /** * Returns all options passed during the construction of the form. * * @return array The passed options. */ public function getOptions(); /** * Returns whether a specific option exists. * * @param string $name The option name, * * @return Boolean Whether the option exists. */ public function hasOption($name); /** * Returns the value of a specific option. * * @param string $name The option name. * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ public function getOption($name, $default = null); } PK!@ @ FormTypeGuesserChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Exception\UnexpectedTypeException; class FormTypeGuesserChain implements FormTypeGuesserInterface { private $guessers = array(); /** * Constructor. * * @param FormTypeGuesserInterface[] $guessers Guessers as instances of FormTypeGuesserInterface * * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface */ public function __construct(array $guessers) { foreach ($guessers as $guesser) { if (!$guesser instanceof FormTypeGuesserInterface) { throw new UnexpectedTypeException($guesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } if ($guesser instanceof self) { $this->guessers = array_merge($this->guessers, $guesser->guessers); } else { $this->guessers[] = $guesser; } } } /** * {@inheritDoc} */ public function guessType($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessType($class, $property); }); } /** * {@inheritDoc} */ public function guessRequired($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessRequired($class, $property); }); } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessMaxLength($class, $property); }); } /** * {@inheritDoc} */ public function guessPattern($class, $property) { return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessPattern($class, $property); }); } /** * Executes a closure for each guesser and returns the best guess from the * return values * * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance * * @return Guess|null The guess with the highest confidence */ private function guess(\Closure $closure) { $guesses = array(); foreach ($this->guessers as $guesser) { if ($guess = $closure($guesser)) { $guesses[] = $guess; } } return Guess::getBestGuess($guesses); } } PK!RGuess/ValueGuess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; /** * Contains a guessed value * * @author Bernhard Schussek */ class ValueGuess extends Guess { /** * The guessed value * @var array */ private $value; /** * Constructor * * @param string $value The guessed value * @param integer $confidence The confidence that the guessed class name * is correct */ public function __construct($value, $confidence) { parent::__construct($confidence); $this->value = $value; } /** * Returns the guessed value * * @return mixed */ public function getValue() { return $this->value; } } PK!51 1 Guess/Guess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * Base class for guesses made by TypeGuesserInterface implementation * * Each instance contains a confidence value about the correctness of the guess. * Thus an instance with confidence HIGH_CONFIDENCE is more likely to be * correct than an instance with confidence LOW_CONFIDENCE. * * @author Bernhard Schussek */ abstract class Guess { /** * Marks an instance with a value that is extremely likely to be correct * @var integer */ const VERY_HIGH_CONFIDENCE = 3; /** * Marks an instance with a value that is very likely to be correct * @var integer */ const HIGH_CONFIDENCE = 2; /** * Marks an instance with a value that is likely to be correct * @var integer */ const MEDIUM_CONFIDENCE = 1; /** * Marks an instance with a value that may be correct * @var integer */ const LOW_CONFIDENCE = 0; /** * The confidence about the correctness of the value * * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE * and LOW_CONFIDENCE. * * @var integer */ private $confidence; /** * Returns the guess most likely to be correct from a list of guesses. * * If there are multiple guesses with the same, highest confidence, the * returned guess is any of them. * * @param Guess[] $guesses An array of guesses * * @return Guess|null The guess with the highest confidence */ public static function getBestGuess(array $guesses) { $result = null; $maxConfidence = -1; foreach ($guesses as $guess) { if ($maxConfidence < $confidence = $guess->getConfidence()) { $maxConfidence = $confidence; $result = $guess; } } return $result; } /** * Constructor. * * @param integer $confidence The confidence * * @throws InvalidArgumentException if the given value of confidence is unknown */ public function __construct($confidence) { if (self::VERY_HIGH_CONFIDENCE !== $confidence && self::HIGH_CONFIDENCE !== $confidence && self::MEDIUM_CONFIDENCE !== $confidence && self::LOW_CONFIDENCE !== $confidence) { throw new InvalidArgumentException('The confidence should be one of the constants defined in Guess.'); } $this->confidence = $confidence; } /** * Returns the confidence that the guessed value is correct. * * @return integer One of the constants VERY_HIGH_CONFIDENCE, * HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE */ public function getConfidence() { return $this->confidence; } } PK!  Guess/TypeGuess.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Guess; /** * Contains a guessed class name and a list of options for creating an instance * of that class * * @author Bernhard Schussek */ class TypeGuess extends Guess { /** * The guessed field type * @var string */ private $type; /** * The guessed options for creating an instance of the guessed class * @var array */ private $options; /** * Constructor * * @param string $type The guessed field type * @param array $options The options for creating instances of the * guessed class * @param integer $confidence The confidence that the guessed class name * is correct */ public function __construct($type, array $options, $confidence) { parent::__construct($confidence); $this->type = $type; $this->options = $options; } /** * Returns the guessed field type * * @return string */ public function getType() { return $this->type; } /** * Returns the guessed options for creating instances of the guessed type * * @return array */ public function getOptions() { return $this->options; } } PK!0\ZZCallbackTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\TransformationFailedException; class CallbackTransformer implements DataTransformerInterface { /** * The callback used for forward transform * @var \Closure */ private $transform; /** * The callback used for reverse transform * @var \Closure */ private $reverseTransform; /** * Constructor. * * @param \Closure $transform The forward transform callback * @param \Closure $reverseTransform The reverse transform callback */ public function __construct(\Closure $transform, \Closure $reverseTransform) { $this->transform = $transform; $this->reverseTransform = $reverseTransform; } /** * Transforms a value from the original representation to a transformed representation. * * @param mixed $data The value in the original representation * * @return mixed The value in the transformed representation * * @throws UnexpectedTypeException when the argument is not a string * @throws TransformationFailedException when the transformation fails */ public function transform($data) { return call_user_func($this->transform, $data); } /** * Transforms a value from the transformed representation to its original * representation. * * @param mixed $data The value in the transformed representation * * @return mixed The value in the original representation * * @throws UnexpectedTypeException when the argument is not of the expected type * @throws TransformationFailedException when the transformation fails */ public function reverseTransform($data) { return call_user_func($this->reverseTransform, $data); } } PK!4Nz"z" Button.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\BadMethodCallException; /** * A form button. * * @author Bernhard Schussek */ class Button implements \IteratorAggregate, FormInterface { /** * @var FormInterface|null */ private $parent; /** * @var FormConfigInterface */ private $config; /** * @var Boolean */ private $submitted = false; /** * Creates a new button from a form configuration. * * @param FormConfigInterface $config The button's configuration. */ public function __construct(FormConfigInterface $config) { $this->config = $config; } /** * Unsupported method. * * @param mixed $offset * * @return Boolean Always returns false. */ public function offsetExists($offset) { return false; } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * * @throws BadMethodCallException */ public function offsetGet($offset) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * @param mixed $value * * @throws BadMethodCallException */ public function offsetSet($offset, $value) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $offset * * @throws BadMethodCallException */ public function offsetUnset($offset) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * {@inheritdoc} */ public function setParent(FormInterface $parent = null) { $this->parent = $parent; } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * Unsupported method. * * This method should not be invoked. * * @param int|string|FormInterface $child * @param null $type * @param array $options * * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function get($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * @param string $name * * @return Boolean Always returns false. */ public function has($name) { return false; } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function remove($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * {@inheritdoc} */ public function all() { return array(); } /** * {@inheritdoc} */ public function getErrors() { return array(); } /** * Unsupported method. * * This method should not be invoked. * * @param string $modelData * * @throws BadMethodCallException */ public function setData($modelData) { // called during initialization of the form tree // noop } /** * Unsupported method. * * @return null Always returns null. */ public function getData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getNormData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getViewData() { return null; } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getExtraData() { return array(); } /** * Returns the button's configuration. * * @return FormConfigInterface The configuration. */ public function getConfig() { return $this->config; } /** * Returns whether the button is submitted. * * @return Boolean true if the button was submitted. */ public function isSubmitted() { return $this->submitted; } /** * Returns the name by which the button is identified in forms. * * @return string The name of the button. */ public function getName() { return $this->config->getName(); } /** * Unsupported method. * * @return null Always returns null. */ public function getPropertyPath() { return null; } /** * Unsupported method. * * @param FormError $error * * @throws BadMethodCallException */ public function addError(FormError $error) { throw new BadMethodCallException('Buttons cannot have errors.'); } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isValid() { return true; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function isRequired() { return false; } /** * {@inheritdoc} */ public function isDisabled() { return $this->config->getDisabled(); } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isEmpty() { return true; } /** * Unsupported method. * * @return Boolean Always returns true. */ public function isSynchronized() { return true; } /** * Unsupported method. * * @throws BadMethodCallException */ public function initialize() { throw new BadMethodCallException('Buttons cannot be initialized. Call initialize() on the root form instead.'); } /** * Unsupported method. * * @param mixed $request * * @throws BadMethodCallException */ public function handleRequest($request = null) { throw new BadMethodCallException('Buttons cannot handle requests. Call handleRequest() on the root form instead.'); } /** * Submits data to the button. * * @param null|string $submittedData The data. * @param Boolean $clearMissing Not used. * * @return Button The button instance * * @throws Exception\AlreadySubmittedException If the button has already been submitted. */ public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); } $this->submitted = true; return $this; } /** * {@inheritdoc} */ public function getRoot() { return $this->parent ? $this->parent->getRoot() : $this; } /** * {@inheritdoc} */ public function isRoot() { return null === $this->parent; } /** * {@inheritdoc} */ public function createView(FormView $parent = null) { if (null === $parent && $this->parent) { $parent = $this->parent->createView(); } $type = $this->config->getType(); $options = $this->config->getOptions(); $view = $type->createView($this, $parent); $type->buildView($view, $this, $options); $type->finishView($view, $this, $options); return $view; } /** * Unsupported method. * * @return integer Always returns 0. */ public function count() { return 0; } /** * Unsupported method. * * @return \EmptyIterator Always returns an empty iterator. */ public function getIterator() { return new \EmptyIterator(); } } PK!-9NNautoloader.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ final class FormEvents { const PRE_SUBMIT = 'form.pre_bind'; const SUBMIT = 'form.bind'; const POST_SUBMIT = 'form.post_bind'; const PRE_SET_DATA = 'form.pre_set_data'; const POST_SET_DATA = 'form.post_set_data'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link PRE_SUBMIT} instead. */ const PRE_BIND = 'form.pre_bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link SUBMIT} instead. */ const BIND = 'form.bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link POST_SUBMIT} instead. */ const POST_BIND = 'form.post_bind'; private function __construct() { } } PK! FormTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ interface FormTypeInterface { /** * Builds the form. * * This method is called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the form. * * @see FormTypeExtensionInterface::buildForm() * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the form view. * * This method is called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the view. * * A view of a form is built before the views of the child forms are built. * This means that you cannot access child views in this method. If you need * to do so, move your logic to {@link finishView()} instead. * * @see FormTypeExtensionInterface::buildView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the form view. * * This method gets called for each type in the hierarchy starting form the * top most type. Type extensions can further modify the view. * * When this method is called, views of the form's children have already * been built and finished and can be accessed. You should only implement * such logic in this method that actually accesses child views. For everything * else you are recommended to implement {@link buildView()} instead. * * @see FormTypeExtensionInterface::finishView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Sets the default options for this type. * * @param OptionsResolverInterface $resolver The resolver for the options. */ public function setDefaultOptions(OptionsResolverInterface $resolver); /** * Returns the name of the parent type. * * You can also return a type instance from this method, although doing so * is discouraged because it leads to a performance penalty. The support * for returning type instances may be dropped from future releases. * * @return string|null|FormTypeInterface The name of the parent type if any, null otherwise. */ public function getParent(); /** * Returns the name of this type. * * @return string The name of this type */ public function getName(); } PK!>FormRegistryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The central registry of the Form component. * * @author Bernhard Schussek */ interface FormRegistryInterface { /** * Returns a form type by name. * * This methods registers the type extensions from the form extensions. * * @param string $name The name of the type * * @return ResolvedFormTypeInterface The type * * @throws Exception\UnexpectedTypeException if the passed name is not a string * @throws Exception\InvalidArgumentException if the type can not be retrieved from any extension */ public function getType($name); /** * Returns whether the given form type is supported. * * @param string $name The name of the type * * @return Boolean Whether the type is supported */ public function hasType($name); /** * Returns the guesser responsible for guessing types. * * @return FormTypeGuesserInterface|null */ public function getTypeGuesser(); /** * Returns the extensions loaded by the framework. * * @return FormExtensionInterface[] */ public function getExtensions(); } PK!?zzFormTypeGuesserInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormTypeGuesserInterface { /** * Returns a field guess for a property name of a class * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\TypeGuess|null A guess for the field's type and options */ public function guessType($class, $property); /** * Returns a guess whether a property of a class is required * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess A guess for the field's required setting */ public function guessRequired($class, $property); /** * Returns a guess about the field's maximum length * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess|null A guess for the field's maximum length */ public function guessMaxLength($class, $property); /** * Returns a guess about the field's pattern * * - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) , lines below * - If this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess. * Example: * You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5) * @link https://github.com/symfony/symfony/pull/3927 * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * * @return Guess\ValueGuess|null A guess for the field's required pattern */ public function guessPattern($class, $property); } PK!*ResolvedFormType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolver; /** * A wrapper for a form type and its extensions. * * @author Bernhard Schussek */ class ResolvedFormType implements ResolvedFormTypeInterface { /** * @var FormTypeInterface */ private $innerType; /** * @var FormTypeExtensionInterface[] */ private $typeExtensions; /** * @var ResolvedFormTypeInterface|null */ private $parent; /** * @var OptionsResolver */ private $optionsResolver; public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null) { if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) { throw new InvalidArgumentException(sprintf( 'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".', get_class($innerType), $innerType->getName() )); } foreach ($typeExtensions as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } } $this->innerType = $innerType; $this->typeExtensions = $typeExtensions; $this->parent = $parent; } /** * {@inheritdoc} */ public function getName() { return $this->innerType->getName(); } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * {@inheritdoc} */ public function getInnerType() { return $this->innerType; } /** * {@inheritdoc} */ public function getTypeExtensions() { // BC if ($this->innerType instanceof AbstractType) { return $this->innerType->getExtensions(); } return $this->typeExtensions; } /** * {@inheritdoc} */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $options = $this->getOptionsResolver()->resolve($options); // Should be decoupled from the specific option at some point $dataClass = isset($options['data_class']) ? $options['data_class'] : null; $builder = $this->newBuilder($name, $dataClass, $factory, $options); $builder->setType($this); return $builder; } /** * {@inheritdoc} */ public function createView(FormInterface $form, FormView $parent = null) { return $this->newView($parent); } /** * Configures a form builder for the type hierarchy. * * @param FormBuilderInterface $builder The builder to configure. * @param array $options The options used for the configuration. */ public function buildForm(FormBuilderInterface $builder, array $options) { if (null !== $this->parent) { $this->parent->buildForm($builder, $options); } $this->innerType->buildForm($builder, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->buildForm($builder, $options); } } /** * Configures a form view for the type hierarchy. * * This method is called before the children of the view are built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function buildView(FormView $view, FormInterface $form, array $options) { if (null !== $this->parent) { $this->parent->buildView($view, $form, $options); } $this->innerType->buildView($view, $form, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->buildView($view, $form, $options); } } /** * Finishes a form view for the type hierarchy. * * This method is called after the children of the view have been built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function finishView(FormView $view, FormInterface $form, array $options) { if (null !== $this->parent) { $this->parent->finishView($view, $form, $options); } $this->innerType->finishView($view, $form, $options); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->finishView($view, $form, $options); } } /** * Returns the configured options resolver used for this type. * * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. */ public function getOptionsResolver() { if (null === $this->optionsResolver) { if (null !== $this->parent) { $this->optionsResolver = clone $this->parent->getOptionsResolver(); } else { $this->optionsResolver = new OptionsResolver(); } $this->innerType->setDefaultOptions($this->optionsResolver); foreach ($this->typeExtensions as $extension) { /* @var FormTypeExtensionInterface $extension */ $extension->setDefaultOptions($this->optionsResolver); } } return $this->optionsResolver; } /** * Creates a new builder instance. * * Override this method if you want to customize the builder class. * * @param string $name The name of the builder. * @param string $dataClass The data class. * @param FormFactoryInterface $factory The current form factory. * @param array $options The builder options. * * @return FormBuilderInterface The new builder instance. */ protected function newBuilder($name, $dataClass, FormFactoryInterface $factory, array $options) { if ($this->innerType instanceof ButtonTypeInterface) { return new ButtonBuilder($name, $options); } if ($this->innerType instanceof SubmitButtonTypeInterface) { return new SubmitButtonBuilder($name, $options); } return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options); } /** * Creates a new view instance. * * Override this method if you want to customize the view class. * * @param FormView|null $parent The parent view, if available. * * @return FormView A new view instance. */ protected function newView(FormView $parent = null) { return new FormView($parent); } } PK!ObXqqSubmitButton.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A button that submits the form. * * @author Bernhard Schussek */ class SubmitButton extends Button implements ClickableInterface { /** * @var Boolean */ private $clicked = false; /** * {@inheritdoc} */ public function isClicked() { return $this->clicked; } /** * Submits data to the button. * * @param null|string $submittedData The data. * @param Boolean $clearMissing Not used. * * @return SubmitButton The button instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function submit($submittedData, $clearMissing = true) { parent::submit($submittedData, $clearMissing); $this->clicked = null !== $submittedData; return $this; } } PK!pAbstractRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Default implementation of {@link FormRendererEngineInterface}. * * @author Bernhard Schussek */ abstract class AbstractRendererEngine implements FormRendererEngineInterface { /** * The variable in {@link FormView} used as cache key. */ const CACHE_KEY_VAR = 'cache_key'; /** * @var array */ protected $defaultThemes; /** * @var array */ protected $themes = array(); /** * @var array */ protected $resources = array(); /** * @var array */ private $resourceHierarchyLevels = array(); /** * Creates a new renderer engine. * * @param array $defaultThemes The default themes. The type of these * themes is open to the implementation. */ public function __construct(array $defaultThemes = array()) { $this->defaultThemes = $defaultThemes; } /** * {@inheritdoc} */ public function setTheme(FormView $view, $themes) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; // Do not cast, as casting turns objects into arrays of properties $this->themes[$cacheKey] = is_array($themes) ? $themes : array($themes); // Unset instead of resetting to an empty array, in order to allow // implementations (like TwigRendererEngine) to check whether $cacheKey // is set at all. unset($this->resources[$cacheKey]); unset($this->resourceHierarchyLevels[$cacheKey]); } /** * {@inheritdoc} */ public function getResourceForBlockName(FormView $view, $blockName) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockName($cacheKey, $view, $blockName); } return $this->resources[$cacheKey][$blockName]; } /** * {@inheritdoc} */ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $blockName = $blockNameHierarchy[$hierarchyLevel]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); } return $this->resources[$cacheKey][$blockName]; } /** * {@inheritdoc} */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $blockName = $blockNameHierarchy[$hierarchyLevel]; if (!isset($this->resources[$cacheKey][$blockName])) { $this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $hierarchyLevel); } // If $block was previously rendered loaded with loadTemplateForBlock(), the template // is cached but the hierarchy level is not. In this case, we know that the block // exists at this very hierarchy level, so we can just set it. if (!isset($this->resourceHierarchyLevels[$cacheKey][$blockName])) { $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; } return $this->resourceHierarchyLevels[$cacheKey][$blockName]; } /** * Loads the cache with the resource for a given block name. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName); /** * Loads the cache with the resource for a specific level of a block hierarchy. * * @see getResourceForBlockHierarchy() * * @param string $cacheKey The cache key used for storing the * resource. * @param FormView $view The form view for finding the applying * themes. * @param array $blockNameHierarchy The block hierarchy, with the most * specific block name at the end. * @param integer $hierarchyLevel The level in the block hierarchy that * should be loaded. * * @return Boolean True if the resource could be loaded, false otherwise. */ private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel) { $blockName = $blockNameHierarchy[$hierarchyLevel]; // Try to find a template for that block if ($this->loadResourceForBlockName($cacheKey, $view, $blockName)) { // If loadTemplateForBlock() returns true, it was able to populate the // cache. The only missing thing is to set the hierarchy level at which // the template was found. $this->resourceHierarchyLevels[$cacheKey][$blockName] = $hierarchyLevel; return true; } if ($hierarchyLevel > 0) { $parentLevel = $hierarchyLevel - 1; $parentBlockName = $blockNameHierarchy[$parentLevel]; // The next two if statements contain slightly duplicated code. This is by intention // and tries to avoid execution of unnecessary checks in order to increase performance. if (isset($this->resources[$cacheKey][$parentBlockName])) { // It may happen that the parent block is already loaded, but its level is not. // In this case, the parent block must have been loaded by loadResourceForBlock(), // which does not check the hierarchy of the block. Subsequently the block must have // been found directly on the parent level. if (!isset($this->resourceHierarchyLevels[$cacheKey][$parentBlockName])) { $this->resourceHierarchyLevels[$cacheKey][$parentBlockName] = $parentLevel; } // Cache the shortcuts for further accesses $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; return true; } if ($this->loadResourceForBlockNameHierarchy($cacheKey, $view, $blockNameHierarchy, $parentLevel)) { // Cache the shortcuts for further accesses $this->resources[$cacheKey][$blockName] = $this->resources[$cacheKey][$parentBlockName]; $this->resourceHierarchyLevels[$cacheKey][$blockName] = $this->resourceHierarchyLevels[$cacheKey][$parentBlockName]; return true; } } // Cache the result for further accesses $this->resources[$cacheKey][$blockName] = false; $this->resourceHierarchyLevels[$cacheKey][$blockName] = false; return false; } } PK!DjNAbstractExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ abstract class AbstractExtension implements FormExtensionInterface { /** * The types provided by this extension * @var FormTypeInterface[] An array of FormTypeInterface */ private $types; /** * The type extensions provided by this extension * @var FormTypeExtensionInterface[] An array of FormTypeExtensionInterface */ private $typeExtensions; /** * The type guesser provided by this extension * @var FormTypeGuesserInterface */ private $typeGuesser; /** * Whether the type guesser has been loaded * @var Boolean */ private $typeGuesserLoaded = false; /** * {@inheritdoc} */ public function getType($name) { if (null === $this->types) { $this->initTypes(); } if (!isset($this->types[$name])) { throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; } /** * {@inheritdoc} */ public function hasType($name) { if (null === $this->types) { $this->initTypes(); } return isset($this->types[$name]); } /** * {@inheritdoc} */ public function getTypeExtensions($name) { if (null === $this->typeExtensions) { $this->initTypeExtensions(); } return isset($this->typeExtensions[$name]) ? $this->typeExtensions[$name] : array(); } /** * {@inheritdoc} */ public function hasTypeExtensions($name) { if (null === $this->typeExtensions) { $this->initTypeExtensions(); } return isset($this->typeExtensions[$name]) && count($this->typeExtensions[$name]) > 0; } /** * {@inheritdoc} */ public function getTypeGuesser() { if (!$this->typeGuesserLoaded) { $this->initTypeGuesser(); } return $this->typeGuesser; } /** * Registers the types. * * @return FormTypeInterface[] An array of FormTypeInterface instances */ protected function loadTypes() { return array(); } /** * Registers the type extensions. * * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface instances */ protected function loadTypeExtensions() { return array(); } /** * Registers the type guesser. * * @return FormTypeGuesserInterface|null A type guesser */ protected function loadTypeGuesser() { return null; } /** * Initializes the types. * * @throws UnexpectedTypeException if any registered type is not an instance of FormTypeInterface */ private function initTypes() { $this->types = array(); foreach ($this->loadTypes() as $type) { if (!$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'Symfony\Component\Form\FormTypeInterface'); } $this->types[$type->getName()] = $type; } } /** * Initializes the type extensions. * * @throws UnexpectedTypeException if any registered type extension is not * an instance of FormTypeExtensionInterface */ private function initTypeExtensions() { $this->typeExtensions = array(); foreach ($this->loadTypeExtensions() as $extension) { if (!$extension instanceof FormTypeExtensionInterface) { throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormTypeExtensionInterface'); } $type = $extension->getExtendedType(); $this->typeExtensions[$type][] = $extension; } } /** * Initializes the type guesser. * * @throws UnexpectedTypeException if the type guesser is not an instance of FormTypeGuesserInterface */ private function initTypeGuesser() { $this->typeGuesserLoaded = true; $this->typeGuesser = $this->loadTypeGuesser(); if (null !== $this->typeGuesser && !$this->typeGuesser instanceof FormTypeGuesserInterface) { throw new UnexpectedTypeException($this->typeGuesser, 'Symfony\Component\Form\FormTypeGuesserInterface'); } } } PK!f#jKFormRendererEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Adapter for rendering form templates with a specific templating engine. * * @author Bernhard Schussek */ interface FormRendererEngineInterface { /** * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. * @param mixed $themes The theme(s). The type of these themes * is open to the implementation. */ public function setTheme(FormView $view, $themes); /** * Returns the resource for a block name. * * The resource is first searched in the themes attached to $view, then * in the themes of its parent view and so on, until a resource was found. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the used themes. * First the themes attached directly to the * view with {@link setTheme()} are considered, * then the ones of its parent etc. * @param string $blockName The name of the block to render. * * @return mixed The renderer resource or false, if none was found. */ public function getResourceForBlockName(FormView $view, $blockName); /** * Returns the resource for a block hierarchy. * * A block hierarchy is an array which starts with the root of the hierarchy * and continues with the child of that root, the child of that child etc. * The following is an example for a block hierarchy: * * * form_widget * text_widget * url_widget * * * In this example, "url_widget" is the most specific block, while the other * blocks are its ancestors in the hierarchy. * * The second parameter $hierarchyLevel determines the level of the hierarchy * that should be rendered. For example, if $hierarchyLevel is 2 for the * above hierarchy, the engine will first look for the block "url_widget", * then, if that does not exist, for the block "text_widget" etc. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the * used themes. First the themes * attached directly to the view * with {@link setTheme()} are * considered, then the ones of * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. * @param integer $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of * $blockNameHierarchy. * * @return mixed The renderer resource or false, if none was found. */ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNameHierarchy, $hierarchyLevel); /** * Returns the hierarchy level at which a resource can be found. * * A block hierarchy is an array which starts with the root of the hierarchy * and continues with the child of that root, the child of that child etc. * The following is an example for a block hierarchy: * * * form_widget * text_widget * url_widget * * * The second parameter $hierarchyLevel determines the level of the hierarchy * that should be rendered. * * If we call this method with the hierarchy level 2, the engine will first * look for a resource for block "url_widget". If such a resource exists, * the method returns 2. Otherwise it tries to find a resource for block * "text_widget" (at level 1) and, again, returns 1 if a resource was found. * The method continues to look for resources until the root level was * reached and nothing was found. In this case false is returned. * * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * * @param FormView $view The view for determining the * used themes. First the themes * attached directly to the view * with {@link setTheme()} are * considered, then the ones of * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. * @param integer $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of * $blockNameHierarchy. * * @return integer|Boolean The hierarchy level or false, if no resource was found. */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel); /** * Renders a block in the given renderer resource. * * The resource can be obtained by calling {@link getResourceForBlock()} * or {@link getResourceForBlockHierarchy()}. The type of the resource is * decided by the implementation. * * @param FormView $view The view to render. * @param mixed $resource The renderer resource. * @param string $blockName The name of the block to render. * @param array $variables The variables to pass to the template. * * @return string The HTML markup. */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()); } PK!11Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\Form\Util\OrderedHashMap; use Symfony\Component\PropertyAccess\PropertyPath; /** * Form represents a form. * * To implement your own form fields, you need to have a thorough understanding * of the data flow within a form. A form stores its data in three different * representations: * * (1) the "model" format required by the form's object * (2) the "normalized" format for internal processing * (3) the "view" format used for display * * A date field, for example, may store a date as "Y-m-d" string (1) in the * object. To facilitate processing in the field, this value is normalized * to a DateTime object (2). In the HTML representation of your form, a * localized string (3) is presented to and modified by the user. * * In most cases, format (1) and format (2) will be the same. For example, * a checkbox field uses a Boolean value for both internal processing and * storage in the object. In these cases you simply need to set a value * transformer to convert between formats (2) and (3). You can do this by * calling addViewTransformer(). * * In some cases though it makes sense to make format (1) configurable. To * demonstrate this, let's extend our above date field to store the value * either as "Y-m-d" string or as timestamp. Internally we still want to * use a DateTime object for processing. To convert the data from string/integer * to DateTime you can set a normalization transformer by calling * addNormTransformer(). The normalized data is then converted to the displayed * data as described before. * * The conversions (1) -> (2) -> (3) use the transform methods of the transformers. * The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers. * * @author Fabien Potencier * @author Bernhard Schussek */ class Form implements \IteratorAggregate, FormInterface { /** * The form's configuration * @var FormConfigInterface */ private $config; /** * The parent of this form * @var FormInterface */ private $parent; /** * The children of this form * @var FormInterface[] A map of FormInterface instances */ private $children; /** * The errors of this form * @var FormError[] An array of FormError instances */ private $errors = array(); /** * Whether this form was submitted * @var Boolean */ private $submitted = false; /** * The button that was used to submit the form * @var Button */ private $clickedButton; /** * The form data in model format * @var mixed */ private $modelData; /** * The form data in normalized format * @var mixed */ private $normData; /** * The form data in view format * @var mixed */ private $viewData; /** * The submitted values that don't belong to any children * @var array */ private $extraData = array(); /** * Whether the data in model, normalized and view format is * synchronized. Data may not be synchronized if transformation errors * occur. * @var Boolean */ private $synchronized = true; /** * Whether the form's data has been initialized. * * When the data is initialized with its default value, that default value * is passed through the transformer chain in order to synchronize the * model, normalized and view format for the first time. This is done * lazily in order to save performance when {@link setData()} is called * manually, making the initialization with the configured default value * superfluous. * * @var Boolean */ private $defaultDataSet = false; /** * Whether setData() is currently being called. * @var Boolean */ private $lockSetData = false; /** * Creates a new form based on the given configuration. * * @param FormConfigInterface $config The form configuration. * * @throws LogicException if a data mapper is not provided for a compound form */ public function __construct(FormConfigInterface $config) { // Compound forms always need a data mapper, otherwise calls to // `setData` and `add` will not lead to the correct population of // the child forms. if ($config->getCompound() && !$config->getDataMapper()) { throw new LogicException('Compound forms need a data mapper'); } // If the form inherits the data from its parent, it is not necessary // to call setData() with the default data. if ($config->getInheritData()) { $this->defaultDataSet = true; } $this->config = $config; $this->children = new OrderedHashMap(); } public function __clone() { $this->children = clone $this->children; foreach ($this->children as $key => $child) { $this->children[$key] = clone $child; } } /** * {@inheritdoc} */ public function getConfig() { return $this->config; } /** * {@inheritdoc} */ public function getName() { return $this->config->getName(); } /** * {@inheritdoc} */ public function getPropertyPath() { if (null !== $this->config->getPropertyPath()) { return $this->config->getPropertyPath(); } if (null === $this->getName() || '' === $this->getName()) { return null; } $parent = $this->parent; while ($parent && $parent->getConfig()->getInheritData()) { $parent = $parent->getParent(); } if ($parent && null === $parent->getConfig()->getDataClass()) { return new PropertyPath('['.$this->getName().']'); } return new PropertyPath($this->getName()); } /** * {@inheritdoc} */ public function isRequired() { if (null === $this->parent || $this->parent->isRequired()) { return $this->config->getRequired(); } return false; } /** * {@inheritDoc} */ public function isDisabled() { if (null === $this->parent || !$this->parent->isDisabled()) { return $this->config->getDisabled(); } return true; } /** * {@inheritdoc} */ public function setParent(FormInterface $parent = null) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot set the parent of a submitted form'); } if (null !== $parent && '' === $this->config->getName()) { throw new LogicException('A form with an empty name cannot have a parent form.'); } $this->parent = $parent; return $this; } /** * {@inheritdoc} */ public function getParent() { return $this->parent; } /** * {@inheritdoc} */ public function getRoot() { return $this->parent ? $this->parent->getRoot() : $this; } /** * {@inheritdoc} */ public function isRoot() { return null === $this->parent; } /** * {@inheritdoc} */ public function setData($modelData) { // If the form is submitted while disabled, it is set to submitted, but the data is not // changed. In such cases (i.e. when the form is not initialized yet) don't // abort this method. if ($this->submitted && $this->defaultDataSet) { throw new AlreadySubmittedException('You cannot change the data of a submitted form.'); } // If the form inherits its parent's data, disallow data setting to // prevent merge conflicts if ($this->config->getInheritData()) { throw new RuntimeException('You cannot change the data of a form inheriting its parent data.'); } // Don't allow modifications of the configured data if the data is locked if ($this->config->getDataLocked() && $modelData !== $this->config->getData()) { return $this; } if (is_object($modelData) && !$this->config->getByReference()) { $modelData = clone $modelData; } if ($this->lockSetData) { throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); } $this->lockSetData = true; $dispatcher = $this->config->getEventDispatcher(); // Hook to change content of the data if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); $modelData = $event->getData(); } // Treat data as strings unless a value transformer exists if (!$this->config->getViewTransformers() && !$this->config->getModelTransformers() && is_scalar($modelData)) { $modelData = (string) $modelData; } // Synchronize representations - must not change the content! $normData = $this->modelToNorm($modelData); $viewData = $this->normToView($normData); // Validate if view data matches data class (unless empty) if (!FormUtil::isEmpty($viewData)) { $dataClass = $this->config->getDataClass(); $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : ' a(n) '.gettype($viewData); if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; throw new LogicException( 'The form\'s view data is expected to be of type '.$expectedType.', ' . 'but is '.$actualType.'. You ' . 'can avoid this error by setting the "data_class" option to ' . '"'.get_class($viewData).'" or by adding a view transformer ' . 'that transforms '.$actualType.' to '.$expectedType.'.' ); } if (null !== $dataClass && !$viewData instanceof $dataClass) { throw new LogicException( 'The form\'s view data is expected to be an instance of class ' . $dataClass.', but is '. $actualType.'. You can avoid this error ' . 'by setting the "data_class" option to null or by adding a view ' . 'transformer that transforms '.$actualType.' to an instance of ' . $dataClass.'.' ); } } $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; $this->defaultDataSet = true; $this->lockSetData = false; // It is not necessary to invoke this method if the form doesn't have children, // even if the form is compound. if (count($this->children) > 0) { // Update child forms from the data $iterator = new InheritDataAwareIterator($this->children); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::POST_SET_DATA, $event); } return $this; } /** * {@inheritdoc} */ public function getData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->modelData; } /** * {@inheritdoc} */ public function getNormData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getNormData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->normData; } /** * {@inheritdoc} */ public function getViewData() { if ($this->config->getInheritData()) { if (!$this->parent) { throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); } return $this->parent->getViewData(); } if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this->viewData; } /** * {@inheritdoc} */ public function getExtraData() { return $this->extraData; } /** * {@inheritdoc} */ public function initialize() { if (null !== $this->parent) { throw new RuntimeException('Only root forms should be initialized.'); } // Guarantee that the *_SET_DATA events have been triggered once the // form is initialized. This makes sure that dynamically added or // removed fields are already visible after initialization. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } return $this; } /** * {@inheritdoc} */ public function handleRequest($request = null) { $this->config->getRequestHandler()->handleRequest($this, $request); return $this; } /** * {@inheritdoc} */ public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); } // Initialize errors in the very beginning so that we don't lose any // errors added during listeners $this->errors = array(); // Obviously, a disabled form should not change its data upon submission. if ($this->isDisabled()) { $this->submitted = true; return $this; } // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners // are always invoked before submit() takes place. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } // Treat false as NULL to support binding false to checkboxes. // Don't convert NULL to a string here in order to determine later // whether an empty value has been submitted or whether no value has // been submitted at all. This is important for processing checkboxes // and radio buttons with empty values. if (false === $submittedData) { $submittedData = null; } elseif (is_scalar($submittedData)) { $submittedData = (string) $submittedData; } $dispatcher = $this->config->getEventDispatcher(); $modelData = null; $normData = null; $viewData = null; try { // Hook to change content of the data submitted by the browser if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { $event = new FormEvent($this, $submittedData); $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); $submittedData = $event->getData(); } // Check whether the form is compound. // This check is preferable over checking the number of children, // since forms without children may also be compound. // (think of empty collection forms) if ($this->config->getCompound()) { if (null === $submittedData) { $submittedData = array(); } if (!is_array($submittedData)) { throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); } foreach ($this->children as $name => $child) { if (array_key_exists($name, $submittedData) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); if (null !== $this->clickedButton) { continue; } if ($child instanceof ClickableInterface && $child->isClicked()) { $this->clickedButton = $child; continue; } if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) { $this->clickedButton = $child->getClickedButton(); } } } $this->extraData = $submittedData; } // Forms that inherit their parents' data also are not processed, // because then it would be too difficult to merge the changes in // the child and the parent form. Instead, the parent form also takes // changes in the grandchildren (i.e. children of the form that inherits // its parent's data) into account. // (see InheritDataAwareIterator below) if (!$this->config->getInheritData()) { // If the form is compound, the default data in view format // is reused. The data of the children is merged into this // default data using the data mapper. // If the form is not compound, the submitted data is also the data in view format. $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; if (FormUtil::isEmpty($viewData)) { $emptyData = $this->config->getEmptyData(); if ($emptyData instanceof \Closure) { /* @var \Closure $emptyData */ $emptyData = $emptyData($this, $viewData); } $viewData = $emptyData; } // Merge form data from children into existing view data // It is not necessary to invoke this method if the form has no children, // even if it is compound. if (count($this->children) > 0) { // Use InheritDataAwareIterator to process children of // descendants that inherit this form's data. // These descendants will not be submitted normally (see the check // for $this->config->getInheritData() above) $childrenIterator = new InheritDataAwareIterator($this->children); $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); } // Normalize data to unified representation $normData = $this->viewToNorm($viewData); // Hook to change content of the data in the normalized // representation if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { $event = new FormEvent($this, $normData); $dispatcher->dispatch(FormEvents::SUBMIT, $event); $normData = $event->getData(); } // Synchronize representations - must not change the content! $modelData = $this->normToModel($normData); $viewData = $this->normToView($normData); } } catch (TransformationFailedException $e) { $this->synchronized = false; // If $viewData was not yet set, set it to $submittedData so that // the erroneous data is accessible on the form. // Forms that inherit data never set any data, because the getters // forward to the parent form's getters anyway. if (null === $viewData && !$this->config->getInheritData()) { $viewData = $submittedData; } } $this->submitted = true; $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { $event = new FormEvent($this, $viewData); $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); } return $this; } /** * Alias of {@link submit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link submit()} instead. */ public function bind($submittedData) { return $this->submit($submittedData); } /** * {@inheritdoc} */ public function addError(FormError $error) { if ($this->parent && $this->config->getErrorBubbling()) { $this->parent->addError($error); } else { $this->errors[] = $error; } return $this; } /** * {@inheritdoc} */ public function isSubmitted() { return $this->submitted; } /** * Alias of {@link isSubmitted()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link isSubmitted()} instead. */ public function isBound() { return $this->submitted; } /** * {@inheritdoc} */ public function isSynchronized() { return $this->synchronized; } /** * {@inheritdoc} */ public function isEmpty() { foreach ($this->children as $child) { if (!$child->isEmpty()) { return false; } } return FormUtil::isEmpty($this->modelData) || // arrays, countables 0 === count($this->modelData) || // traversables that are not countable ($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)); } /** * {@inheritdoc} */ public function isValid() { if (!$this->submitted) { return false; } if (count($this->errors) > 0) { return false; } if ($this->isDisabled()) { return true; } foreach ($this->children as $child) { if ($child->isSubmitted() && !$child->isValid()) { return false; } } return true; } /** * Returns the button that was used to submit the form. * * @return Button|null The clicked button or NULL if the form was not * submitted */ public function getClickedButton() { if ($this->clickedButton) { return $this->clickedButton; } if ($this->parent && method_exists($this->parent, 'getClickedButton')) { return $this->parent->getClickedButton(); } return null; } /** * {@inheritdoc} */ public function getErrors() { return $this->errors; } /** * Returns a string representation of all form errors (including children errors). * * This method should only be used to help debug a form. * * @param integer $level The indentation level (used internally) * * @return string A string representation of all errors */ public function getErrorsAsString($level = 0) { $errors = ''; foreach ($this->errors as $error) { $errors .= str_repeat(' ', $level).'ERROR: '.$error->getMessage()."\n"; } foreach ($this->children as $key => $child) { $errors .= str_repeat(' ', $level).$key.":\n"; if ($child instanceof self && $err = $child->getErrorsAsString($level + 4)) { $errors .= $err; } else { $errors .= str_repeat(' ', $level + 4)."No errors\n"; } } return $errors; } /** * {@inheritdoc} */ public function all() { return iterator_to_array($this->children); } /** * {@inheritdoc} */ public function add($child, $type = null, array $options = array()) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot add children to a submitted form'); } if (!$this->config->getCompound()) { throw new LogicException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); } // Obtain the view data $viewData = null; // If setData() is currently being called, there is no need to call // mapDataToForms() here, as mapDataToForms() is called at the end // of setData() anyway. Not doing this check leads to an endless // recursion when initializing the form lazily and an event listener // (such as ResizeFormListener) adds fields depending on the data: // // * setData() is called, the form is not initialized yet // * add() is called by the listener (setData() is not complete, so // the form is still not initialized) // * getViewData() is called // * setData() is called since the form is not initialized yet // * ... endless recursion ... // // Also skip data mapping if setData() has not been called yet. // setData() will be called upon form initialization and data mapping // will take place by then. if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $viewData = $this->getViewData(); } if (!$child instanceof FormInterface) { if (!is_string($child) && !is_int($child)) { throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } // Never initialize child forms automatically $options['auto_initialize'] = false; if (null === $type) { $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); } else { $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options); } } elseif ($child->getConfig()->getAutoInitialize()) { throw new RuntimeException(sprintf( 'Automatic initialization is only supported on root forms. You '. 'should set the "auto_initialize" option to false on the field "%s".', $child->getName() )); } $this->children[$child->getName()] = $child; $child->setParent($this); if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child))); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } return $this; } /** * {@inheritdoc} */ public function remove($name) { if ($this->submitted) { throw new AlreadySubmittedException('You cannot remove children from a submitted form'); } if (isset($this->children[$name])) { $this->children[$name]->setParent(null); unset($this->children[$name]); } return $this; } /** * {@inheritdoc} */ public function has($name) { return isset($this->children[$name]); } /** * {@inheritdoc} */ public function get($name) { if (isset($this->children[$name])) { return $this->children[$name]; } throw new OutOfBoundsException(sprintf('Child "%s" does not exist.', $name)); } /** * Returns whether a child with the given name exists (implements the \ArrayAccess interface). * * @param string $name The name of the child * * @return Boolean */ public function offsetExists($name) { return $this->has($name); } /** * Returns the child with the given name (implements the \ArrayAccess interface). * * @param string $name The name of the child * * @return FormInterface The child form * * @throws \OutOfBoundsException If the named child does not exist. */ public function offsetGet($name) { return $this->get($name); } /** * Adds a child to the form (implements the \ArrayAccess interface). * * @param string $name Ignored. The name of the child is used. * @param FormInterface $child The child to be added. * * @throws AlreadySubmittedException If the form has already been submitted. * @throws LogicException When trying to add a child to a non-compound form. * * @see self::add() */ public function offsetSet($name, $child) { $this->add($child); } /** * Removes the child with the given name from the form (implements the \ArrayAccess interface). * * @param string $name The name of the child to remove * * @throws AlreadySubmittedException If the form has already been submitted. */ public function offsetUnset($name) { $this->remove($name); } /** * Returns the iterator for this group. * * @return \Traversable */ public function getIterator() { return $this->children; } /** * Returns the number of form children (implements the \Countable interface). * * @return integer The number of embedded form children */ public function count() { return count($this->children); } /** * {@inheritdoc} */ public function createView(FormView $parent = null) { if (null === $parent && $this->parent) { $parent = $this->parent->createView(); } $type = $this->config->getType(); $options = $this->config->getOptions(); // The methods createView(), buildView() and finishView() are called // explicitly here in order to be able to override either of them // in a custom resolved form type. $view = $type->createView($this, $parent); $type->buildView($view, $this, $options); foreach ($this->children as $name => $child) { $view->children[$name] = $child->createView($view); } $type->finishView($view, $this, $options); return $view; } /** * Normalizes the value if a normalization transformer is set. * * @param mixed $value The value to transform * * @return mixed */ private function modelToNorm($value) { foreach ($this->config->getModelTransformers() as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Reverse transforms a value if a normalization transformer is set. * * @param string $value The value to reverse transform * * @return mixed */ private function normToModel($value) { $transformers = $this->config->getModelTransformers(); for ($i = count($transformers) - 1; $i >= 0; --$i) { $value = $transformers[$i]->reverseTransform($value); } return $value; } /** * Transforms the value if a value transformer is set. * * @param mixed $value The value to transform * * @return mixed */ private function normToView($value) { // Scalar values should be converted to strings to // facilitate differentiation between empty ("") and zero (0). // Only do this for simple forms, as the resulting value in // compound forms is passed to the data mapper and thus should // not be converted to a string before. if (!$this->config->getViewTransformers() && !$this->config->getCompound()) { return null === $value || is_scalar($value) ? (string) $value : $value; } foreach ($this->config->getViewTransformers() as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Reverse transforms a value if a value transformer is set. * * @param string $value The value to reverse transform * * @return mixed */ private function viewToNorm($value) { $transformers = $this->config->getViewTransformers(); if (!$transformers) { return '' === $value ? null : $value; } for ($i = count($transformers) - 1; $i >= 0; --$i) { $value = $transformers[$i]->reverseTransform($value); } return $value; } } PK!di$Exception/BadMethodCallException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base BadMethodCallException for the Form component. * * @author Bernhard Schussek */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } PK!W  #Exception/AlreadyBoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Alias of {@link AlreadySubmittedException}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link AlreadySubmittedException} instead. */ class AlreadyBoundException extends LogicException { } PK!(dd+Exception/InvalidConfigurationException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class InvalidConfigurationException extends InvalidArgumentException { } PK!_c==%Exception/UnexpectedTypeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class UnexpectedTypeException extends InvalidArgumentException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } PK!SD+Exception/TransformationFailedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Indicates a value transformation error. * * @author Bernhard Schussek */ class TransformationFailedException extends RuntimeException { } PK!é"Exception/OutOfBoundsException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base OutOfBoundsException for Form component. * * @author Alexander Kotynia */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } PK!yu Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base ExceptionInterface for the Form component. * * @author Bernhard Schussek */ interface ExceptionInterface { } PK!NException/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base RuntimeException for the Form component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } PK!K9'Exception/AlreadySubmittedException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Thrown when an operation is called that is not acceptable after submitting * a form. * * @author Bernhard Schussek */ class AlreadySubmittedException extends AlreadyBoundException { } PK!1;TT#Exception/ErrorMappingException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class ErrorMappingException extends RuntimeException { } PK!+RR!Exception/StringCastException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; class StringCastException extends RuntimeException { } PK!XException/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base LogicException for Form component. * * @author Alexander Kotynia */ class LogicException extends \LogicException implements ExceptionInterface { } PK!gBz&Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Exception; /** * Base InvalidArgumentException for the Form component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } PK!188AbstractType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ abstract class AbstractType implements FormTypeInterface { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { } /** * {@inheritdoc} */ public function getParent() { return 'form'; } } PK!I 66Util/OrderedHashMap.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * A hash map which keeps track of deletions and additions. * * Like in associative arrays, elements can be mapped to integer or string keys. * Unlike associative arrays, the map keeps track of the order in which keys * were added and removed. This order is reflected during iteration. * * The map supports concurrent modification during iteration. That means that * you can insert and remove elements from within a foreach loop and the * iterator will reflect those changes accordingly. * * While elements that are added during the loop are recognized by the iterator, * changed elements are not. Otherwise the loop could be infinite if each loop * changes the current element: * * $map = new OrderedHashMap(); * $map[1] = 1; * $map[2] = 2; * $map[3] = 3; * * foreach ($map as $index => $value) { * echo "$index: $value\n" * if (1 === $index) { * $map[1] = 4; * $map[] = 5; * } * } * * print_r(iterator_to_array($map)); * * // => 1: 1 * // 2: 2 * // 3: 3 * // 4: 5 * // Array * // ( * // [1] => 4 * // [2] => 2 * // [3] => 3 * // [4] => 5 * // ) * * The map also supports multiple parallel iterators. That means that you can * nest foreach loops without affecting each other's iteration: * * foreach ($map as $index => $value) { * foreach ($map as $index2 => $value2) { * // ... * } * } * * @author Bernhard Schussek * * @since 2.2.6 */ class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The elements of the map, indexed by their keys. * * @var array */ private $elements = array(); /** * The keys of the map in the order in which they were inserted or changed. * * @var array */ private $orderedKeys = array(); /** * References to the cursors of all open iterators. * * @var array */ private $managedCursors = array(); /** * Creates a new map. * * @param array $elements The elements to insert initially. * * @since 2.2.6 */ public function __construct(array $elements = array()) { $this->elements = $elements; $this->orderedKeys = array_keys($elements); } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetExists($key) { return isset($this->elements[$key]); } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetGet($key) { if (!isset($this->elements[$key])) { throw new \OutOfBoundsException('The offset "' . $key . '" does not exist.'); } return $this->elements[$key]; } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetSet($key, $value) { if (null === $key || !isset($this->elements[$key])) { if (null === $key) { $key = array() === $this->orderedKeys // If the array is empty, use 0 as key ? 0 // Imitate PHP's behavior of generating a key that equals // the highest existing integer key + 1 : max($this->orderedKeys) + 1; } $this->orderedKeys[] = $key; } $this->elements[$key] = $value; } /** * {@inheritdoc} * * @since 2.2.6 */ public function offsetUnset($key) { if (false !== ($position = array_search($key, $this->orderedKeys))) { array_splice($this->orderedKeys, $position, 1); unset($this->elements[$key]); foreach ($this->managedCursors as $i => $cursor) { if ($cursor >= $position) { --$this->managedCursors[$i]; } } } } /** * {@inheritdoc} * * @since 2.2.6 */ public function getIterator() { return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors); } /** * {@inheritdoc} * * @since 2.2.6 */ public function count() { return count($this->elements); } } PK!h''Util/OrderedHashMapIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator for {@link OrderedHashMap} objects. * * This class is internal and should not be used. * * @author Bernhard Schussek * * @since 2.2.6 */ class OrderedHashMapIterator implements \Iterator { /** * @var array */ private $elements; /** * @var array */ private $orderedKeys; /** * @var integer */ private $cursor; /** * @var integer */ private $cursorId; /** * @var array */ private $managedCursors; /** * @var string|integer|null */ private $key; /** * @var mixed */ private $current; /** * Creates a new iterator. * * @param array $elements The elements of the map, indexed by their * keys. * @param array $orderedKeys The keys of the map in the order in which * they should be iterated. * @param array $managedCursors An array from which to reference the * iterator's cursor as long as it is alive. * This array is managed by the corresponding * {@link OrderedHashMap} instance to support * recognizing the deletion of elements. * * @since 2.2.6 */ public function __construct(array &$elements, array &$orderedKeys, array &$managedCursors) { $this->elements = &$elements; $this->orderedKeys = &$orderedKeys; $this->managedCursors = &$managedCursors; $this->cursorId = count($managedCursors); $this->managedCursors[$this->cursorId] = &$this->cursor; } /** * Removes the iterator's cursors from the managed cursors of the * corresponding {@link OrderedHashMap} instance. * * @since 2.2.6 */ public function __destruct() { // Use array_splice() instead of isset() to prevent holes in the // array indices, which would break the initialization of $cursorId array_splice($this->managedCursors, $this->cursorId, 1); } /** *{@inheritdoc} * * @since 2.2.6 */ public function current() { return $this->current; } /** * {@inheritdoc} * * @since 2.2.6 */ public function next() { ++$this->cursor; if (isset($this->orderedKeys[$this->cursor])) { $this->key = $this->orderedKeys[$this->cursor]; $this->current = $this->elements[$this->key]; } else { $this->key = null; $this->current = null; } } /** *{@inheritdoc} * * @since 2.2.6 */ public function key() { return $this->key; } /** *{@inheritdoc} * * @since 2.2.6 */ public function valid() { return null !== $this->key; } /** *{@inheritdoc} * * @since 2.2.6 */ public function rewind() { $this->cursor = 0; if (isset($this->orderedKeys[0])) { $this->key = $this->orderedKeys[0]; $this->current = $this->elements[$this->key]; } else { $this->key = null; $this->current = null; } } } PK!F22!Util/VirtualFormAwareIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator that traverses an array of forms. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link InheritDataAwareIterator} instead. */ class VirtualFormAwareIterator extends \IteratorIterator implements \RecursiveIterator { /** * {@inheritdoc} */ public function getChildren() { return new static($this->current()); } /** *{@inheritdoc} */ public function hasChildren() { return (bool) $this->current()->getConfig()->getInheritData(); } } PK!y$$Util/FormUtil.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * @author Bernhard Schussek */ class FormUtil { /** * This class should not be instantiated */ private function __construct() {} /** * Returns whether the given data is empty. * * This logic is reused multiple times throughout the processing of * a form and needs to be consistent. PHP's keyword `empty` cannot * be used as it also considers 0 and "0" to be empty. * * @param mixed $data * * @return Boolean */ public static function isEmpty($data) { // Should not do a check for array() === $data!!! // This method is used in occurrences where arrays are // not considered to be empty, ever. return null === $data || '' === $data; } } PK!<!Util/InheritDataAwareIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Util; /** * Iterator that traverses an array of forms. * * Contrary to \ArrayIterator, this iterator recognizes changes in the original * array during iteration. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. * * @author Bernhard Schussek */ class InheritDataAwareIterator extends VirtualFormAwareIterator { } PK!QTppSubmitButtonBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A builder for {@link SubmitButton} instances. * * @author Bernhard Schussek */ class SubmitButtonBuilder extends ButtonBuilder { /** * Creates the button. * * @return SubmitButton The button */ public function getForm() { return new SubmitButton($this->getFormConfig()); } } PK!z5ResolvedFormTypeFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ class ResolvedFormTypeFactory implements ResolvedFormTypeFactoryInterface { /** * {@inheritdoc} */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) { return new ResolvedFormType($type, $typeExtensions, $parent); } } PK!Sf PreloadedExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A form extension with preloaded types, type exceptions and type guessers. * * @author Bernhard Schussek */ class PreloadedExtension implements FormExtensionInterface { /** * @var array */ private $types = array(); /** * @var array */ private $typeExtensions = array(); /** * @var FormTypeGuesserInterface */ private $typeGuesser; /** * Creates a new preloaded extension. * * @param FormTypeInterface[] $types The types that the extension should support. * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support. * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. */ public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) { $this->types = $types; $this->typeExtensions = $typeExtensions; $this->typeGuesser = $typeGuesser; } /** * {@inheritdoc} */ public function getType($name) { if (!isset($this->types[$name])) { throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; } /** * {@inheritdoc} */ public function hasType($name) { return isset($this->types[$name]); } /** * {@inheritdoc} */ public function getTypeExtensions($name) { return isset($this->typeExtensions[$name]) ? $this->typeExtensions[$name] : array(); } /** * {@inheritdoc} */ public function hasTypeExtensions($name) { return !empty($this->typeExtensions[$name]); } /** * {@inheritdoc} */ public function getTypeGuesser() { return $this->typeGuesser; } } PK!>*iiFormFactory.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; class FormFactory implements FormFactoryInterface { /** * @var FormRegistryInterface */ private $registry; /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; public function __construct(FormRegistryInterface $registry, ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { $this->registry = $registry; $this->resolvedTypeFactory = $resolvedTypeFactory; } /** * {@inheritdoc} */ public function create($type = 'form', $data = null, array $options = array()) { return $this->createBuilder($type, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createNamed($name, $type = 'form', $data = null, array $options = array()) { return $this->createNamedBuilder($name, $type, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createForProperty($class, $property, $data = null, array $options = array()) { return $this->createBuilderForProperty($class, $property, $data, $options)->getForm(); } /** * {@inheritdoc} */ public function createBuilder($type = 'form', $data = null, array $options = array()) { $name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface ? $type->getName() : $type; return $this->createNamedBuilder($name, $type, $data, $options); } /** * {@inheritdoc} */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()) { if (null !== $data && !array_key_exists('data', $options)) { $options['data'] = $data; } if ($type instanceof FormTypeInterface) { $type = $this->resolveType($type); } elseif (is_string($type)) { $type = $this->registry->getType($type); } elseif (!$type instanceof ResolvedFormTypeInterface) { throw new UnexpectedTypeException($type, 'string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface'); } $builder = $type->createBuilder($this, $name, $options); // Explicitly call buildForm() in order to be able to override either // createBuilder() or buildForm() in the resolved form type $type->buildForm($builder, $builder->getOptions()); return $builder; } /** * {@inheritdoc} */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()) { if (null === $guesser = $this->registry->getTypeGuesser()) { return $this->createNamedBuilder($property, 'text', $data, $options); } $typeGuess = $guesser->guessType($class, $property); $maxLengthGuess = $guesser->guessMaxLength($class, $property); $requiredGuess = $guesser->guessRequired($class, $property); $patternGuess = $guesser->guessPattern($class, $property); $type = $typeGuess ? $typeGuess->getType() : 'text'; $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null; $pattern = $patternGuess ? $patternGuess->getValue() : null; if (null !== $pattern) { $options = array_merge(array('pattern' => $pattern), $options); } if (null !== $maxLength) { $options = array_merge(array('max_length' => $maxLength), $options); } if ($requiredGuess) { $options = array_merge(array('required' => $requiredGuess->getValue()), $options); } // user options may override guessed options if ($typeGuess) { $options = array_merge($typeGuess->getOptions(), $options); } return $this->createNamedBuilder($property, $type, $data, $options); } /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. * * @param FormTypeInterface $type The type to resolve. * * @return ResolvedFormTypeInterface The resolved type. */ private function resolveType(FormTypeInterface $type) { $parentType = $type->getParent(); if ($parentType instanceof FormTypeInterface) { $parentType = $this->resolveType($parentType); } elseif (null !== $parentType) { $parentType = $this->registry->getType($parentType); } return $this->resolvedTypeFactory->createResolvedType( $type, // Type extensions are not supported for unregistered type instances, // i.e. type instances that are passed to the FormFactory directly, // nor for their parents, if getParent() also returns a type instance. array(), $parentType ); } } PK!\gRequestHandlerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Submits forms if they were submitted. * * @author Bernhard Schussek */ interface RequestHandlerInterface { /** * Submits a form if it was submitted. * * @param FormInterface $form The form to submit. * @param mixed $request The current request. */ public function handleRequest(FormInterface $form, $request = null); } PK!+qDAA Test/FormPerformanceTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; /** * Base class for performance tests. * * Copied from Doctrine 2's OrmPerformanceTestCase. * * @author robo * @author Bernhard Schussek */ abstract class FormPerformanceTestCase extends FormIntegrationTestCase { /** * @var integer */ protected $maxRunningTime = 0; /** */ protected function runTest() { $s = microtime(true); parent::runTest(); $time = microtime(true) - $s; if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) { $this->fail( sprintf( 'expected running time: <= %s but was: %s', $this->maxRunningTime, $time ) ); } } /** * @param integer $maxRunningTime * @throws \InvalidArgumentException */ public function setMaxRunningTime($maxRunningTime) { if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { $this->maxRunningTime = $maxRunningTime; } else { throw new \InvalidArgumentException(); } } /** * @return integer * @since Method available since Release 2.3.0 */ public function getMaxRunningTime() { return $this->maxRunningTime; } } PK!sŪTest/TypeTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; abstract class TypeTestCase extends FormIntegrationTestCase { /** * @var FormBuilder */ protected $builder; /** * @var EventDispatcher */ protected $dispatcher; protected function setUp() { parent::setUp(); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); } public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); } } PK!,7// Test/DeprecationErrorHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormEvent; class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) { if ($errorNumber & E_USER_DEPRECATED) { return true; } return \PHPUnit_Util_ErrorHandler::handleError($errorNumber, $message, $file, $line); } public static function handleBC($errorNumber, $message, $file, $line, $context) { if ($errorNumber & E_USER_DEPRECATED) { return true; } return false; } public static function preBind($listener, FormEvent $event) { set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $listener->preBind($event); restore_error_handler(); } } PK!B4I++ Test/FormIntegrationTestCase.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\Forms; /** * @author Bernhard Schussek */ abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\FormFactoryInterface */ protected $factory; protected function setUp() { $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); } protected function getExtensions() { return array(); } } PK!myyTest/FormBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; interface FormBuilderInterface extends \Iterator, \Symfony\Component\Form\FormBuilderInterface { } PK!a(0kkTest/FormInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Test; interface FormInterface extends \Iterator, \Symfony\Component\Form\FormInterface { } PK!nFormExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Interface for extensions which provide types, type extensions and a guesser. */ interface FormExtensionInterface { /** * Returns a type by name. * * @param string $name The name of the type * * @return FormTypeInterface The type * * @throws Exception\InvalidArgumentException if the given type is not supported by this extension */ public function getType($name); /** * Returns whether the given type is supported. * * @param string $name The name of the type * * @return Boolean Whether the type is supported by this extension */ public function hasType($name); /** * Returns the extensions for the given type. * * @param string $name The name of the type * * @return FormTypeExtensionInterface[] An array of extensions as FormTypeExtensionInterface instances */ public function getTypeExtensions($name); /** * Returns whether this extension provides type extensions for the given type. * * @param string $name The name of the type * * @return Boolean Whether the given type has extensions */ public function hasTypeExtensions($name); /** * Returns the type guesser provided by this extension. * * @return FormTypeGuesserInterface|null The type guesser */ public function getTypeGuesser(); } PK!|G ResolvedFormTypeInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A wrapper for a form type and its extensions. * * @author Bernhard Schussek */ interface ResolvedFormTypeInterface { /** * Returns the name of the type. * * @return string The type name. */ public function getName(); /** * Returns the parent type. * * @return ResolvedFormTypeInterface|null The parent type or null. */ public function getParent(); /** * Returns the wrapped form type. * * @return FormTypeInterface The wrapped form type. */ public function getInnerType(); /** * Returns the extensions of the wrapped form type. * * @return FormTypeExtensionInterface[] An array of {@link FormTypeExtensionInterface} instances. */ public function getTypeExtensions(); /** * Creates a new form builder for this type. * * @param FormFactoryInterface $factory The form factory. * @param string $name The name for the builder. * @param array $options The builder options. * * @return FormBuilderInterface The created form builder. */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()); /** * Creates a new form view for a form of this type. * * @param FormInterface $form The form to create a view for. * @param FormView $parent The parent view or null. * * @return FormView The created form view. */ public function createView(FormInterface $form, FormView $parent = null); /** * Configures a form builder for the type hierarchy. * * @param FormBuilderInterface $builder The builder to configure. * @param array $options The options used for the configuration. */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Configures a form view for the type hierarchy. * * It is called before the children of the view are built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes a form view for the type hierarchy. * * It is called after the children of the view have been built. * * @param FormView $view The form view to configure. * @param FormInterface $form The form corresponding to the view. * @param array $options The options used for the configuration. */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Returns the configured options resolver used for this type. * * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. */ public function getOptionsResolver(); } PK!{d!!FormConfigBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * @author Bernhard Schussek */ interface FormConfigBuilderInterface extends FormConfigInterface { /** * Adds an event listener to an event on this form. * * @param string $eventName The name of the event to listen to. * @param callable $listener The listener to execute. * @param integer $priority The priority of the listener. Listeners * with a higher priority are called before * listeners with a lower priority. * * @return self The configuration object. */ public function addEventListener($eventName, $listener, $priority = 0); /** * Adds an event subscriber for events on this form. * * @param EventSubscriberInterface $subscriber The subscriber to attach. * * @return self The configuration object. */ public function addEventSubscriber(EventSubscriberInterface $subscriber); /** * Appends / prepends a transformer to the view transformer chain. * * The transform method of the transformer is used to convert data from the * normalized to the view format. * The reverseTransform method of the transformer is used to convert from the * view to the normalized format. * * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend if set to true, prepend instead of appending * * @return self The configuration object. */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false); /** * Clears the view transformers. * * @return self The configuration object. */ public function resetViewTransformers(); /** * Prepends / appends a transformer to the normalization transformer chain. * * The transform method of the transformer is used to convert data from the * model to the normalized format. * The reverseTransform method of the transformer is used to convert from the * normalized to the model format. * * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend if set to true, append instead of prepending * * @return self The configuration object. */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false); /** * Clears the normalization transformers. * * @return self The configuration object. */ public function resetModelTransformers(); /** * Sets the value for an attribute. * * @param string $name The name of the attribute * @param string $value The value of the attribute * * @return self The configuration object. */ public function setAttribute($name, $value); /** * Sets the attributes. * * @param array $attributes The attributes. * * @return self The configuration object. */ public function setAttributes(array $attributes); /** * Sets the data mapper used by the form. * * @param DataMapperInterface $dataMapper * * @return self The configuration object. */ public function setDataMapper(DataMapperInterface $dataMapper = null); /** * Set whether the form is disabled. * * @param Boolean $disabled Whether the form is disabled * * @return self The configuration object. */ public function setDisabled($disabled); /** * Sets the data used for the client data when no value is submitted. * * @param mixed $emptyData The empty data. * * @return self The configuration object. */ public function setEmptyData($emptyData); /** * Sets whether errors bubble up to the parent. * * @param Boolean $errorBubbling * * @return self The configuration object. */ public function setErrorBubbling($errorBubbling); /** * Sets whether this field is required to be filled out when submitted. * * @param Boolean $required * * @return self The configuration object. */ public function setRequired($required); /** * Sets the property path that the form should be mapped to. * * @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath * The property path or null if the path should be set * automatically based on the form's name. * * @return self The configuration object. */ public function setPropertyPath($propertyPath); /** * Sets whether the form should be mapped to an element of its * parent's data. * * @param Boolean $mapped Whether the form should be mapped. * * @return self The configuration object. */ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * * @param Boolean $byReference Whether the data should be * modified by reference. * * @return self The configuration object. */ public function setByReference($byReference); /** * Sets whether the form should read and write the data of its parent. * * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return self The configuration object. */ public function setInheritData($inheritData); /** * Sets whether the form should be compound. * * @param Boolean $compound Whether the form should be compound. * * @return self The configuration object. * * @see FormConfigInterface::getCompound() */ public function setCompound($compound); /** * Set the types. * * @param ResolvedFormTypeInterface $type The type of the form. * * @return self The configuration object. */ public function setType(ResolvedFormTypeInterface $type); /** * Sets the initial data of the form. * * @param array $data The data of the form in application format. * * @return self The configuration object. */ public function setData($data); /** * Locks the form's data to the data passed in the configuration. * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by * submitting the form. * * @param Boolean $locked Whether to lock the default data. * * @return self The configuration object. */ public function setDataLocked($locked); /** * Sets the form factory used for creating new forms. * * @param FormFactoryInterface $formFactory The form factory. */ public function setFormFactory(FormFactoryInterface $formFactory); /** * Sets the target URL of the form. * * @param string $action The target URL of the form. * * @return self The configuration object. */ public function setAction($action); /** * Sets the HTTP method used by the form. * * @param string $method The HTTP method of the form. * * @return self The configuration object. */ public function setMethod($method); /** * Sets the request handler used by the form. * * @param RequestHandlerInterface $requestHandler * * @return self The configuration object. */ public function setRequestHandler(RequestHandlerInterface $requestHandler); /** * Sets whether the form should be initialized automatically. * * Should be set to true only for root forms. * * @param Boolean $initialize True to initialize the form automatically, * false to suppress automatic initialization. * In the second case, you need to call * {@link FormInterface::initialize()} manually. * * @return self The configuration object. */ public function setAutoInitialize($initialize); /** * Builds and returns the form configuration. * * @return FormConfigInterface */ public function getFormConfig(); } PK!ɃT FormFactoryBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A builder for FormFactoryInterface objects. * * @author Bernhard Schussek */ interface FormFactoryBuilderInterface { /** * Sets the factory for creating ResolvedFormTypeInterface instances. * * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory * * @return FormFactoryBuilderInterface The builder. */ public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory); /** * Adds an extension to be loaded by the factory. * * @param FormExtensionInterface $extension The extension. * * @return FormFactoryBuilderInterface The builder. */ public function addExtension(FormExtensionInterface $extension); /** * Adds a list of extensions to be loaded by the factory. * * @param FormExtensionInterface[] $extensions The extensions. * * @return FormFactoryBuilderInterface The builder. */ public function addExtensions(array $extensions); /** * Adds a form type to the factory. * * @param FormTypeInterface $type The form type. * * @return FormFactoryBuilderInterface The builder. */ public function addType(FormTypeInterface $type); /** * Adds a list of form types to the factory. * * @param FormTypeInterface[] $types The form types. * * @return FormFactoryBuilderInterface The builder. */ public function addTypes(array $types); /** * Adds a form type extension to the factory. * * @param FormTypeExtensionInterface $typeExtension The form type extension. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeExtension(FormTypeExtensionInterface $typeExtension); /** * Adds a list of form type extensions to the factory. * * @param FormTypeExtensionInterface[] $typeExtensions The form type extensions. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeExtensions(array $typeExtensions); /** * Adds a type guesser to the factory. * * @param FormTypeGuesserInterface $typeGuesser The type guesser. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser); /** * Adds a list of type guessers to the factory. * * @param FormTypeGuesserInterface[] $typeGuessers The type guessers. * * @return FormFactoryBuilderInterface The builder. */ public function addTypeGuessers(array $typeGuessers); /** * Builds and returns the factory. * * @return FormFactoryInterface The form factory. */ public function getFormFactory(); } PK!N̷$ResolvedFormTypeFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Creates ResolvedFormTypeInterface instances. * * This interface allows you to use your custom ResolvedFormTypeInterface * implementation, within which you can customize the concrete FormBuilderInterface * implementations or FormView subclasses that are used by the framework. * * @author Bernhard Schussek */ interface ResolvedFormTypeFactoryInterface { /** * Resolves a form type. * * @param FormTypeInterface $type * @param FormTypeExtensionInterface[] $typeExtensions * @param ResolvedFormTypeInterface|null $parent * * @return ResolvedFormTypeInterface * * @throws Exception\UnexpectedTypeException if the types parent {@link FormTypeInterface::getParent()} is not a string * @throws Exception\InvalidArgumentException if the types parent can not be retrieved from any extension */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null); } PK!2FormFactoryBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * The default implementation of FormFactoryBuilderInterface. * * @author Bernhard Schussek */ class FormFactoryBuilder implements FormFactoryBuilderInterface { /** * @var ResolvedFormTypeFactoryInterface */ private $resolvedTypeFactory; /** * @var array */ private $extensions = array(); /** * @var array */ private $types = array(); /** * @var array */ private $typeExtensions = array(); /** * @var array */ private $typeGuessers = array(); /** * {@inheritdoc} */ public function setResolvedTypeFactory(ResolvedFormTypeFactoryInterface $resolvedTypeFactory) { $this->resolvedTypeFactory = $resolvedTypeFactory; return $this; } /** * {@inheritdoc} */ public function addExtension(FormExtensionInterface $extension) { $this->extensions[] = $extension; return $this; } /** * {@inheritdoc} */ public function addExtensions(array $extensions) { $this->extensions = array_merge($this->extensions, $extensions); return $this; } /** * {@inheritdoc} */ public function addType(FormTypeInterface $type) { $this->types[$type->getName()] = $type; return $this; } /** * {@inheritdoc} */ public function addTypes(array $types) { foreach ($types as $type) { $this->types[$type->getName()] = $type; } return $this; } /** * {@inheritdoc} */ public function addTypeExtension(FormTypeExtensionInterface $typeExtension) { $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension; return $this; } /** * {@inheritdoc} */ public function addTypeExtensions(array $typeExtensions) { foreach ($typeExtensions as $typeExtension) { $this->typeExtensions[$typeExtension->getExtendedType()][] = $typeExtension; } return $this; } /** * {@inheritdoc} */ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser) { $this->typeGuessers[] = $typeGuesser; return $this; } /** * {@inheritdoc} */ public function addTypeGuessers(array $typeGuessers) { $this->typeGuessers = array_merge($this->typeGuessers, $typeGuessers); return $this; } /** * {@inheritdoc} */ public function getFormFactory() { $extensions = $this->extensions; if (count($this->types) > 0 || count($this->typeExtensions) > 0 || count($this->typeGuessers) > 0) { if (count($this->typeGuessers) > 1) { $typeGuesser = new FormTypeGuesserChain($this->typeGuessers); } else { $typeGuesser = isset($this->typeGuessers[0]) ? $this->typeGuessers[0] : null; } $extensions[] = new PreloadedExtension($this->types, $this->typeExtensions, $typeGuesser); } $resolvedTypeFactory = $this->resolvedTypeFactory ?: new ResolvedFormTypeFactory(); $registry = new FormRegistry($extensions, $resolvedTypeFactory); return new FormFactory($registry, $resolvedTypeFactory); } } PK!CAbstractTypeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ abstract class AbstractTypeExtension implements FormTypeExtensionInterface { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { } } PK!E FormRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Renders a form into HTML. * * @author Bernhard Schussek */ interface FormRendererInterface { /** * Returns the engine used by this renderer. * * @return FormRendererEngineInterface The renderer engine. */ public function getEngine(); /** * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. * @param mixed $themes The theme(s). The type of these themes * is open to the implementation. */ public function setTheme(FormView $view, $themes); /** * Renders a named block of the form theme. * * @param FormView $view The view for which to render the block. * @param string $blockName The name of the block. * @param array $variables The variables to pass to the template. * * @return string The HTML markup */ public function renderBlock(FormView $view, $blockName, array $variables = array()); /** * Searches and renders a block for a given name suffix. * * The block is searched by combining the block names stored in the * form view with the given suffix. If a block name is found, that * block is rendered. * * If this method is called recursively, the block search is continued * where a block was found before. * * @param FormView $view The view for which to render the block. * @param string $blockNameSuffix The suffix of the block name. * @param array $variables The variables to pass to the template. * * @return string The HTML markup */ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $variables = array()); /** * Renders a CSRF token. * * Use this helper for CSRF protection without the overhead of creating a * form. * * * * * * Check the token in your action using the same token ID. * * * $csrfProvider = $this->get('security.csrf.token_generator'); * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } * * * @param string $tokenId The ID of the CSRF token * * @return string A CSRF token */ public function renderCsrfToken($tokenId); /** * Makes a technical name human readable. * * Sequences of underscores are replaced by single spaces. The first letter * of the resulting string is capitalized, while all other letters are * turned to lowercase. * * @param string $text The text to humanize. * * @return string The humanized text. */ public function humanize($text); } PK!:  FormBuilderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuilderInterface { /** * Adds a new field to this group. A field must have a unique name within * the group. Otherwise the existing field is overwritten. * * If you add a nested group, this group should also be represented in the * object hierarchy. * * @param string|integer|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * * @return FormBuilderInterface The builder object. */ public function add($child, $type = null, array $options = array()); /** * Creates a form builder. * * @param string $name The name of the form or the name of the property * @param string|FormTypeInterface $type The type of the form or null if name is a property * @param array $options The options * * @return FormBuilderInterface The created builder. */ public function create($name, $type = null, array $options = array()); /** * Returns a child by name. * * @param string $name The name of the child * * @return FormBuilderInterface The builder for the child * * @throws Exception\InvalidArgumentException if the given child does not exist */ public function get($name); /** * Removes the field with the given name. * * @param string $name * * @return FormBuilderInterface The builder object. */ public function remove($name); /** * Returns whether a field with the given name exists. * * @param string $name * * @return Boolean */ public function has($name); /** * Returns the children. * * @return array */ public function all(); /** * Creates the form. * * @return Form The form */ public function getForm(); } PK!Z)FormFactoryInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface FormFactoryInterface { /** * Returns a form. * * @see createBuilder() * * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormInterface The form named after the type * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function create($type = 'form', $data = null, array $options = array()); /** * Returns a form. * * @see createNamedBuilder() * * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormInterface The form * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamed($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form for a property of a class. * * @see createBuilderForProperty() * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * @param mixed $data The initial data * @param array $options The options for the builder * * @return FormInterface The form named after the property * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createForProperty($class, $property, $data = null, array $options = array()); /** * Returns a form builder. * * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilderInterface The form builder * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createBuilder($type = 'form', $data = null, array $options = array()); /** * Returns a form builder. * * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilderInterface The form builder * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form builder for a property of a class. * * If any of the 'max_length', 'required' and type options can be guessed, * and are not provided in the options argument, the guessed value is used. * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * @param mixed $data The initial data * @param array $options The options for the builder * * @return FormBuilderInterface The form builder named after the property * * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()); } PK!YBReversedTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Reverses a transformer * * When the transform() method is called, the reversed transformer's * reverseTransform() method is called and vice versa. * * @author Bernhard Schussek */ class ReversedTransformer implements DataTransformerInterface { /** * The reversed transformer * @var DataTransformerInterface */ protected $reversedTransformer; /** * Reverses this transformer * * @param DataTransformerInterface $reversedTransformer */ public function __construct(DataTransformerInterface $reversedTransformer) { $this->reversedTransformer = $reversedTransformer; } /** * {@inheritDoc} */ public function transform($value) { return $this->reversedTransformer->reverseTransform($value); } /** * {@inheritDoc} */ public function reverseTransform($value) { return $this->reversedTransformer->transform($value); } } PK!rW W DataTransformerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms a value between different representations. * * @author Bernhard Schussek */ interface DataTransformerInterface { /** * Transforms a value from the original representation to a transformed representation. * * This method is called on two occasions inside a form field: * * 1. When the form field is initialized with the data attached from the datasource (object or array). * 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data * back into the renderable format. For example if you have a date field and submit '2009-10-10' * you might accept this value because its easily parsed, but the transformer still writes back * "2009/10/10" onto the form field (for further displaying or other purposes). * * This method must be able to deal with empty values. Usually this will * be NULL, but depending on your implementation other empty values are * possible as well (such as empty strings). The reasoning behind this is * that value transformers must be chainable. If the transform() method * of the first value transformer outputs NULL, the second value transformer * must be able to process that value. * * By convention, transform() should return an empty string if NULL is * passed. * * @param mixed $value The value in the original representation * * @return mixed The value in the transformed representation * * @throws TransformationFailedException When the transformation fails. */ public function transform($value); /** * Transforms a value from the transformed representation to its original * representation. * * This method is called when {@link Form::submit()} is called to transform the requests tainted data * into an acceptable format for your data processing/model layer. * * This method must be able to deal with empty values. Usually this will * be an empty string, but depending on your implementation other empty * values are possible as well (such as empty strings). The reasoning behind * this is that value transformers must be chainable. If the * reverseTransform() method of the first value transformer outputs an * empty string, the second value transformer must be able to process that * value. * * By convention, reverseTransform() should return NULL if an empty string * is passed. * * @param mixed $value The value in the transformed representation * * @return mixed The value in the original representation * * @throws TransformationFailedException When the transformation fails. */ public function reverseTransform($value); } PK!Wb[H[HButtonBuilder.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\BadMethodCallException; /** * A builder for {@link Button} instances. * * @author Bernhard Schussek */ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface { /** * @var Boolean */ protected $locked = false; /** * @var Boolean */ private $disabled; /** * @var ResolvedFormTypeInterface */ private $type; /** * @var string */ private $name; /** * @var array */ private $attributes = array(); /** * @var array */ private $options; /** * Creates a new button builder. * * @param string $name The name of the button. * @param array $options The button's options. * * @throws InvalidArgumentException If the name is empty. */ public function __construct($name, array $options = array()) { if (empty($name) && 0 != $name) { throw new InvalidArgumentException('Buttons cannot have empty names.'); } $this->name = (string) $name; $this->options = $options; } /** * Unsupported method. * * This method should not be invoked. * * @param string|integer|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * @param string|FormTypeInterface $type * @param array $options * * @throws BadMethodCallException */ public function create($name, $type = null, array $options = array()) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function get($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * This method should not be invoked. * * @param string $name * * @throws BadMethodCallException */ public function remove($name) { throw new BadMethodCallException('Buttons cannot have children.'); } /** * Unsupported method. * * @param string $name * * @return Boolean Always returns false. */ public function has($name) { return false; } /** * Returns the children. * * @return array Always returns an empty array. */ public function all() { return array(); } /** * Creates the button. * * @return Button The button */ public function getForm() { return new Button($this->getFormConfig()); } /** * Unsupported method. * * This method should not be invoked. * * @param string $eventName * @param callable $listener * @param integer $priority * * @throws BadMethodCallException */ public function addEventListener($eventName, $listener, $priority = 0) { throw new BadMethodCallException('Buttons do not support event listeners.'); } /** * Unsupported method. * * This method should not be invoked. * * @param EventSubscriberInterface $subscriber * * @throws BadMethodCallException */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { throw new BadMethodCallException('Buttons do not support event subscribers.'); } /** * Unsupported method. * * This method should not be invoked. * * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend * * @throws BadMethodCallException */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @throws BadMethodCallException */ public function resetViewTransformers() { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend * * @throws BadMethodCallException */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * Unsupported method. * * This method should not be invoked. * * @throws BadMethodCallException */ public function resetModelTransformers() { throw new BadMethodCallException('Buttons do not support data transformers.'); } /** * {@inheritdoc} */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * {@inheritdoc} */ public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * Unsupported method. * * This method should not be invoked. * * @param DataMapperInterface $dataMapper * * @throws BadMethodCallException */ public function setDataMapper(DataMapperInterface $dataMapper = null) { throw new BadMethodCallException('Buttons do not support data mappers.'); } /** * Set whether the button is disabled. * * @param Boolean $disabled Whether the button is disabled * * @return ButtonBuilder The button builder. */ public function setDisabled($disabled) { $this->disabled = $disabled; } /** * Unsupported method. * * This method should not be invoked. * * @param mixed $emptyData * * @throws BadMethodCallException */ public function setEmptyData($emptyData) { throw new BadMethodCallException('Buttons do not support empty data.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $errorBubbling * * @throws BadMethodCallException */ public function setErrorBubbling($errorBubbling) { throw new BadMethodCallException('Buttons do not support error bubbling.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $required * * @throws BadMethodCallException */ public function setRequired($required) { throw new BadMethodCallException('Buttons cannot be required.'); } /** * Unsupported method. * * This method should not be invoked. * * @param null $propertyPath * * @throws BadMethodCallException */ public function setPropertyPath($propertyPath) { throw new BadMethodCallException('Buttons do not support property paths.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $mapped * * @throws BadMethodCallException */ public function setMapped($mapped) { throw new BadMethodCallException('Buttons do not support data mapping.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $byReference * * @throws BadMethodCallException */ public function setByReference($byReference) { throw new BadMethodCallException('Buttons do not support data mapping.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $virtual * * @throws BadMethodCallException */ public function setVirtual($virtual) { throw new BadMethodCallException('Buttons cannot be virtual.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $compound * * @throws BadMethodCallException */ public function setCompound($compound) { throw new BadMethodCallException('Buttons cannot be compound.'); } /** * Sets the type of the button. * * @param ResolvedFormTypeInterface $type The type of the button. * * @return ButtonBuilder The button builder. */ public function setType(ResolvedFormTypeInterface $type) { $this->type = $type; } /** * Unsupported method. * * This method should not be invoked. * * @param array $data * * @throws BadMethodCallException */ public function setData($data) { throw new BadMethodCallException('Buttons do not support data.'); } /** * Unsupported method. * * This method should not be invoked. * * @param Boolean $locked * * @throws BadMethodCallException */ public function setDataLocked($locked) { throw new BadMethodCallException('Buttons do not support data locking.'); } /** * Unsupported method. * * This method should not be invoked. * * @param FormFactoryInterface $formFactory * * @return void * * @throws BadMethodCallException */ public function setFormFactory(FormFactoryInterface $formFactory) { throw new BadMethodCallException('Buttons do not support form factories.'); } /** * Unsupported method. * * @param string $action * * @throws BadMethodCallException */ public function setAction($action) { throw new BadMethodCallException('Buttons do not support actions.'); } /** * Unsupported method. * * @param string $method * * @throws BadMethodCallException */ public function setMethod($method) { throw new BadMethodCallException('Buttons do not support methods.'); } /** * Unsupported method. * * @param RequestHandlerInterface $requestHandler * * @throws BadMethodCallException */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { throw new BadMethodCallException('Buttons do not support form processors.'); } /** * Unsupported method. * * @param Boolean $initialize * * @throws BadMethodCallException */ public function setAutoInitialize($initialize) { if (true === $initialize) { throw new BadMethodCallException('Buttons do not support automatic initialization.'); } return $this; } /** * Unsupported method. * * @param Boolean $inheritData * * @throws BadMethodCallException */ public function setInheritData($inheritData) { throw new BadMethodCallException('Buttons do not support data inheritance.'); } /** * Builds and returns the button configuration. * * @return FormConfigInterface */ public function getFormConfig() { // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; return $config; } /** * Unsupported method. * * @return null Always returns null. */ public function getEventDispatcher() { return null; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * Unsupported method. * * @return null Always returns null. */ public function getPropertyPath() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getMapped() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getByReference() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getVirtual() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getCompound() { return false; } /** * Returns the form type used to construct the button. * * @return ResolvedFormTypeInterface The button's type. */ public function getType() { return $this->type; } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getViewTransformers() { return array(); } /** * Unsupported method. * * @return array Always returns an empty array. */ public function getModelTransformers() { return array(); } /** * Unsupported method. * * @return null Always returns null. */ public function getDataMapper() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getRequired() { return false; } /** * Returns whether the button is disabled. * * @return Boolean Whether the button is disabled. */ public function getDisabled() { return $this->disabled; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getErrorBubbling() { return false; } /** * Unsupported method. * * @return null Always returns null. */ public function getEmptyData() { return null; } /** * Returns additional attributes of the button. * * @return array An array of key-value combinations. */ public function getAttributes() { return $this->attributes; } /** * Returns whether the attribute with the given name exists. * * @param string $name The attribute name. * * @return Boolean Whether the attribute exists. */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Returns the value of the given attribute. * * @param string $name The attribute name. * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ public function getAttribute($name, $default = null) { return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * Unsupported method. * * @return null Always returns null. */ public function getData() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getDataClass() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getDataLocked() { return false; } /** * Unsupported method. * * @return null Always returns null. */ public function getFormFactory() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getAction() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getMethod() { return null; } /** * Unsupported method. * * @return null Always returns null. */ public function getRequestHandler() { return null; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getAutoInitialize() { return false; } /** * Unsupported method. * * @return Boolean Always returns false. */ public function getInheritData() { return false; } /** * Returns all options passed during the construction of the button. * * @return array The passed options. */ public function getOptions() { return $this->options; } /** * Returns whether a specific option exists. * * @param string $name The option name, * * @return Boolean Whether the option exists. */ public function hasOption($name) { return array_key_exists($name, $this->options); } /** * Returns the value of a specific option. * * @param string $name The option name. * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ public function getOption($name, $default = null) { return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** * Unsupported method. * * @return integer Always returns 0. */ public function count() { return 0; } /** * Unsupported method. * * @return \EmptyIterator Always returns an empty iterator. */ public function getIterator() { return new \EmptyIterator(); } } PK!n(Resources/translations/validators.en.xlfnu[ This form should not contain extra fields. This form should not contain extra fields. The uploaded file was too large. Please try to upload a smaller file. The uploaded file was too large. Please try to upload a smaller file. The CSRF token is invalid. Please try to resubmit the form. The CSRF token is invalid. Please try to resubmit the form. PK!誫(Resources/translations/validators.sk.xlfnu[ This form should not contain extra fields. Polia by nemali obsahovať ďalšie prvky. The uploaded file was too large. Please try to upload a smaller file. Odoslaný súbor je príliš veľký. Prosím odošlite súbor s menšou veľkosťou. The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Prosím skúste znovu odoslať formulár. PK!<yy(Resources/translations/validators.uk.xlfnu[ This form should not contain extra fields. Ця форма не повинна містити додаткових полів. The uploaded file was too large. Please try to upload a smaller file. Завантажений файл занадто великий. Будь-ласка, спробуйте завантажити файл меншого розміру. The CSRF token is invalid. Please try to resubmit the form. CSRF значення недопустиме. Будь-ласка, спробуйте відправити форму знову. PK!:(Resources/translations/validators.pl.xlfnu[ This form should not contain extra fields. Ten formularz nie powinien zawierać dodatkowych pól. The uploaded file was too large. Please try to upload a smaller file. Wgrany plik był za duży. Proszę spróbować wgrać mniejszy plik. The CSRF token is invalid. Please try to resubmit the form. Token CSRF jest nieprawidłowy. Proszę spróbować wysłać formularz ponownie. PK! (Resources/translations/validators.pt.xlfnu[ This form should not contain extra fields. Este formulário não deveria conter campos extra. The uploaded file was too large. Please try to upload a smaller file. O arquivo enviado é muito grande. Por favor, tente enviar um ficheiro mais pequeno. The CSRF token is invalid. Please try to resubmit the form. O token CSRF é inválido. Por favor submeta o formulário novamente. PK!%(Resources/translations/validators.lv.xlfnu[ This form should not contain extra fields. Šajā veidlapā nevajadzētu būt papildus ievades laukiem. The uploaded file was too large. Please try to upload a smaller file. Augšupielādētā faila izmērs bija par lielu. Lūdzu mēģiniet augšupielādēt mazāka izmēra failu. The CSRF token is invalid. Please try to resubmit the form. Dotais CSRF talons nav derīgs. Lūdzu mēģiniet vēlreiz iesniegt veidlapu. PK!္o33-Resources/translations/validators.sr_Cyrl.xlfnu[ This form should not contain extra fields. Овај формулар не треба да садржи додатна поља. The uploaded file was too large. Please try to upload a smaller file. Отпремљена датотека је била превелика. Молим покушајте отпремање мање датотеке. The CSRF token is invalid. Please try to resubmit the form. CSRF вредност је невалидна. Покушајте поново. PK!(Resources/translations/validators.fi.xlfnu[ This field group should not contain extra fields. Tämä kenttäryhmä ei voi sisältää ylimääräisiä kenttiä. The uploaded file was too large. Please try to upload a smaller file. Ladattu tiedosto on liian iso. Ole hyvä ja lataa pienempi tiedosto. The CSRF token is invalid. Please try to resubmit the form. CSRF tarkiste on virheellinen. Olen hyvä ja yritä lähettää lomake uudestaan. PK!0h(Resources/translations/validators.es.xlfnu[ This form should not contain extra fields. Este formulario no debería contener campos adicionales. The uploaded file was too large. Please try to upload a smaller file. El archivo subido es demasiado grande. Por favor, suba un archivo más pequeño. The CSRF token is invalid. Please try to resubmit the form. El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario. PK!TI(Resources/translations/validators.de.xlfnu[ This form should not contain extra fields. Dieses Formular sollte keine zusätzlichen Felder enthalten. The uploaded file was too large. Please try to upload a smaller file. Die hochgeladene Datei ist zu groß. Versuchen Sie bitte eine kleinere Datei hochzuladen. The CSRF token is invalid. Please try to resubmit the form. Der CSRF-Token ist ungültig. Versuchen Sie bitte das Formular erneut zu senden. PK!!aZ(Resources/translations/validators.it.xlfnu[ This form should not contain extra fields. Questo form non dovrebbe contenere nessun campo extra. The uploaded file was too large. Please try to upload a smaller file. Il file caricato è troppo grande. Per favore caricare un file più piccolo. The CSRF token is invalid. Please try to resubmit the form. Il token CSRF non è valido. Provare a reinviare il form. PK! !(Resources/translations/validators.ca.xlfnu[ This form should not contain extra fields. Aquest formulari no hauria de contenir camps addicionals. The uploaded file was too large. Please try to upload a smaller file. L'arxiu pujat és massa gran. Per favor, pugi un arxiu més petit. The CSRF token is invalid. Please try to resubmit the form. El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari. PK!(Resources/translations/validators.mn.xlfnu[ This form should not contain extra fields. Форм нэмэлт талбар багтаах боломжгүй. The uploaded file was too large. Please try to upload a smaller file. Upload хийсэн файл хэтэрхий том байна. Бага хэмжээтэй файл оруулна уу. The CSRF token is invalid. Please try to resubmit the form. CSRF token буруу байна. Формоо дахин илгээнэ үү. PK!-(Resources/translations/validators.ru.xlfnu[ This form should not contain extra fields. Эта форма не должна содержать дополнительных полей. The uploaded file was too large. Please try to upload a smaller file. Загруженный файл слишком большой. Пожалуйста, попробуйте загрузить файл меньшего размера. The CSRF token is invalid. Please try to resubmit the form. CSRF значение недопустимо. Пожалуйста, попробуйте повторить отправку формы. PK!3Ե^^(Resources/translations/validators.bg.xlfnu[ This form should not contain extra fields. Тази форма не трябва да съдържа допълнителни полета. The uploaded file was too large. Please try to upload a smaller file. Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл. The CSRF token is invalid. Please try to resubmit the form. Невалиден CSRF токен. Моля, опитайте да изпратите формата отново. PK!Ed(Resources/translations/validators.ro.xlfnu[ This form should not contain extra fields. Aceast formular nu ar trebui să conțină câmpuri suplimentare. The uploaded file was too large. Please try to upload a smaller file. Fișierul încărcat a fost prea mare. Vă rugăm sa încărcați un fișier mai mic. The CSRF token is invalid. Please try to resubmit the form. Token-ul CSRF este invalid. Vă rugăm să trimiteți formularul incă o dată. PK!O(Resources/translations/validators.nl.xlfnu[ This form should not contain extra fields. Dit formulier mag geen extra velden bevatten. The uploaded file was too large. Please try to upload a smaller file. Het geüploade bestand is te groot. Probeer een kleiner bestand te uploaden. The CSRF token is invalid. Please try to resubmit the form. De CSRF-token is ongeldig. Probeer het formulier opnieuw te versturen. PK!S*(Resources/translations/validators.et.xlfnu[ This form should not contain extra fields. Väljade grupp ei tohiks sisalda lisaväljasid. The uploaded file was too large. Please try to upload a smaller file. Üleslaaditud fail oli liiga suur. Palun proovi uuesti väiksema failiga. The CSRF token is invalid. Please try to resubmit the form. CSRF-märgis on vigane. Palun proovi vormi uuesti esitada. PK!V5(Resources/translations/validators.fa.xlfnu[ This form should not contain extra fields. این فرم نباید فیلد اضافی داشته باشد. The uploaded file was too large. Please try to upload a smaller file. فایل بارگذاری شده بسیار بزرگ است. لطفا فایل کوچکتری را بارگزاری کنید. The CSRF token is invalid. Please try to resubmit the form. مقدار CSRF نامعتبر است. لطفا فرم را مجددا ارسال فرمایید.. PK!q(Resources/translations/validators.id.xlfnu[ This form should not contain extra fields. Gabungan kolom tidak boleh mengandung kolom tambahan. The uploaded file was too large. Please try to upload a smaller file. Berkas yang di unggah terlalu besar. Silahkan coba unggah berkas yang lebih kecil. The CSRF token is invalid. Please try to resubmit the form. CSRF-Token tidak sah. Silahkan coba kirim ulang formulir. PK! (Resources/translations/validators.cs.xlfnu[ This form should not contain extra fields. Tato skupina polí nesmí obsahovat další pole. The uploaded file was too large. Please try to upload a smaller file. Nahraný soubor je příliš velký. Nahrajte prosím menší soubor. The CSRF token is invalid. Please try to resubmit the form. CSRF token je neplatný. Zkuste prosím znovu odeslat formulář. PK!8,:+Resources/translations/validators.zh_CN.xlfnu[ This form should not contain extra fields. 该表单中不可有额外字段. The uploaded file was too large. Please try to upload a smaller file. 上传文件太大, 请重新尝试上传一个较小的文件. The CSRF token is invalid. Please try to resubmit the form. CSRF 验证符无效, 请重新提交. PK!Hq(Resources/translations/validators.lt.xlfnu[ This form should not contain extra fields. Forma negali turėti papildomų laukų. The uploaded file was too large. Please try to upload a smaller file. Įkelta byla yra per didelė. bandykite įkelti mažesnę. The CSRF token is invalid. Please try to resubmit the form. CSRF kodas nepriimtinas. Bandykite siųsti formos užklausą dar kartą. PK!_8(Resources/translations/validators.fr.xlfnu[ This form should not contain extra fields. Ce formulaire ne doit pas contenir des champs supplémentaires. The uploaded file was too large. Please try to upload a smaller file. Le fichier téléchargé est trop volumineux. Merci d'essayer d'envoyer un fichier plus petit. The CSRF token is invalid. Please try to resubmit the form. Le jeton CSRF est invalide. Veuillez renvoyer le formulaire. PK!A4(Resources/translations/validators.gl.xlfnu[ This form should not contain extra fields. Este formulario non debería conter campos adicionais. The uploaded file was too large. Please try to upload a smaller file. O arquivo subido é demasiado grande. Por favor, suba un arquivo máis pequeno. The CSRF token is invalid. Please try to resubmit the form. O token CSRF non é válido. Por favor, probe a enviar novamente o formulario. PK! b8(Resources/translations/validators.hr.xlfnu[ This form should not contain extra fields. Ovaj obrazac ne smije sadržavati dodatna polja. The uploaded file was too large. Please try to upload a smaller file. Prenesena datoteka je prevelika. Molim pokušajte prenijeti manju datoteku. The CSRF token is invalid. Please try to resubmit the form. CSRF vrijednost nije ispravna. Pokušajte ponovo poslati obrazac. PK!WgUugg(Resources/translations/validators.nb.xlfnu[ This form should not contain extra fields. Feltgruppen må ikke inneholde ekstra felter. The uploaded file was too large. Please try to upload a smaller file. Den opplastede file var for stor. Vennligst last opp en mindre fil. The CSRF token is invalid. CSRF nøkkelen er ugyldig. PK!ٻ||(Resources/translations/validators.eu.xlfnu[ This form should not contain extra fields. Formulario honek ez luke aparteko eremurik eduki behar. The uploaded file was too large. Please try to upload a smaller file. Igotako fitxategia handiegia da. Mesedez saiatu fitxategi txikiago bat igotzen. The CSRF token is invalid. CSFR tokena ez da egokia. PK!4@+Resources/translations/validators.pt_BR.xlfnu[ This form should not contain extra fields. Este formulário não deve conter campos adicionais. The uploaded file was too large. Please try to upload a smaller file. O arquivo enviado é muito grande. Por favor, tente enviar um arquivo menor. The CSRF token is invalid. Please try to resubmit the form. O token CSRF é inválido. Por favor, tente reenviar o formulário. PK!5(Resources/translations/validators.sl.xlfnu[ This form should not contain extra fields. Ta obrazec ne sme vsebovati dodatnih polj. The uploaded file was too large. Please try to upload a smaller file. Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo. The CSRF token is invalid. Please try to resubmit the form. CSRF vrednost je napačna. Prosimo, ponovno pošljite obrazec. PK!*{(Resources/translations/validators.lb.xlfnu[ This form should not contain extra fields. Dës Feldergrupp sollt keng zousätzlech Felder enthalen. The uploaded file was too large. Please try to upload a smaller file. De geschécktene Fichier ass ze grouss. Versicht wann ech gelift ee méi klenge Fichier eropzelueden. The CSRF token is invalid. Please try to resubmit the form. Den CSRF-Token ass ongëlteg. Versicht wann ech gelift de Formulaire nach eng Kéier ze schécken. PK!be@(Resources/translations/validators.hu.xlfnu[ This form should not contain extra fields. Ez a mezőcsoport nem tartalmazhat extra mezőket. The uploaded file was too large. Please try to upload a smaller file. A feltöltött fájl túl nagy. Kérem próbáljon egy kisebb fájlt feltölteni. The CSRF token is invalid. Please try to resubmit the form. Érvénytelen CSRF token. Kérem próbálja újra elküldeni az űrlapot. PK!_Π(Resources/translations/validators.el.xlfnu[ This form should not contain extra fields. Αυτή η φόρμα δεν πρέπει να περιέχει επιπλέον πεδία. The uploaded file was too large. Please try to upload a smaller file. Το αρχείο είναι πολύ μεγάλο. Παρακαλούμε προσπαθήστε να ανεβάσετε ένα μικρότερο αρχείο. The CSRF token is invalid. Please try to resubmit the form. Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά. PK!X(Resources/translations/validators.da.xlfnu[ This form should not contain extra fields. Feltgruppen må ikke indeholde ekstra felter. The uploaded file was too large. Please try to upload a smaller file. Den oploadede fil var for stor. Opload venligst en mindre fil. The CSRF token is invalid. Please try to resubmit the form. CSRF nøglen er ugyldig. PK!(Resources/translations/validators.ja.xlfnu[ This form should not contain extra fields. フィールドグループに追加のフィールドを含んではなりません。 The uploaded file was too large. Please try to upload a smaller file. アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください。 The CSRF token is invalid. CSRFトークンが無効です。 PK!s>ll(Resources/translations/validators.sv.xlfnu[ This form should not contain extra fields. Formuläret kan inte innehålla extra fält. The uploaded file was too large. Please try to upload a smaller file. Den uppladdade filen var för stor. Försök ladda upp en mindre fil. The CSRF token is invalid. CSRF-symbolen är inte giltig. PK!y99(Resources/translations/validators.hy.xlfnu[ This form should not contain extra fields. Այս ձևը չպետք է պարունակի լրացուցիչ տողեր. The uploaded file was too large. Please try to upload a smaller file. Վերբեռնված ֆայլը չափազանց մեծ է: Խնդրվում է վերբեռնել ավելի փոքր չափսի ֆայլ. The CSRF token is invalid. Please try to resubmit the form. CSRF արժեքը անթույլատրելի է: Փորձեք նորից ուղարկել ձևը. PK!|C(Resources/translations/validators.ar.xlfnu[ This form should not contain extra fields. هذا النموذج يجب الا يحتوى على اى حقول اضافية. The uploaded file was too large. Please try to upload a smaller file. مساحة الملف المرسل كبيرة. من فضلك حاول ارسال ملف اصغر. The CSRF token is invalid. Please try to resubmit the form. قيمة رمز الموقع غير صحيحة. من فضلك اعد ارسال النموذج. PK!r-Resources/translations/validators.sr_Latn.xlfnu[ This form should not contain extra fields. Ovaj formular ne treba da sadrži dodatna polja. The uploaded file was too large. Please try to upload a smaller file. Otpremljena datoteka je bila prevelika. Molim pokušajte otpremanje manje datoteke. The CSRF token is invalid. Please try to resubmit the form. CSRF vrednost je nevalidna. Pokušajte ponovo. PK!NP\(Resources/translations/validators.he.xlfnu[ This form should not contain extra fields. הטופס לא צריך להכיל שדות נוספים. The uploaded file was too large. Please try to upload a smaller file. הקובץ שהועלה גדול מדי. נסה להעלות קובץ קטן יותר. The CSRF token is invalid. אסימון CSRF אינו חוקי. PK!xfh..Resources/config/validation.xmlnu[ PK!R}jjDataMapperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * @author Bernhard Schussek */ interface DataMapperInterface { /** * Maps properties of some data to a list of forms. * * @param mixed $data Structured data. * @param FormInterface[] $forms A list of {@link FormInterface} instances. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ public function mapDataToForms($data, $forms); /** * Maps the data of a list of forms into the properties of some data. * * @param FormInterface[] $forms A list of {@link FormInterface} instances. * @param mixed $data Structured data. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ public function mapFormsToData($forms, &$data); } PK!s FormInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A form group bundling multiple forms in a hierarchical structure. * * @author Bernhard Schussek */ interface FormInterface extends \ArrayAccess, \Traversable, \Countable { /** * Sets the parent form. * * @param FormInterface|null $parent The parent form or null if it's the root. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to set a parent for a form with * an empty name. */ public function setParent(FormInterface $parent = null); /** * Returns the parent form. * * @return FormInterface|null The parent form or null if there is none. */ public function getParent(); /** * Adds or replaces a child to the form. * * @param FormInterface|string|integer $child The FormInterface instance or the name of the child. * @param string|null $type The child's type, if a name was passed. * @param array $options The child's options, if a name was passed. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to add a child to a non-compound form. * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ public function add($child, $type = null, array $options = array()); /** * Returns the child with the given name. * * @param string $name The name of the child * * @return FormInterface The child form * * @throws \OutOfBoundsException If the named child does not exist. */ public function get($name); /** * Returns whether a child with the given name exists. * * @param string $name The name of the child * * @return Boolean */ public function has($name); /** * Removes a child from the form. * * @param string $name The name of the child to remove * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function remove($name); /** * Returns all children in this group. * * @return FormInterface[] An array of FormInterface instances */ public function all(); /** * Returns all errors. * * @return FormError[] An array of FormError instances that occurred during validation */ public function getErrors(); /** * Updates the form with default data. * * @param mixed $modelData The data formatted as expected for the underlying object * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if * the view data does not match the expected type * according to {@link FormConfigInterface::getDataClass}. */ public function setData($modelData); /** * Returns the data in the format needed for the underlying object. * * @return mixed */ public function getData(); /** * Returns the normalized data of the field. * * @return mixed When the field is not submitted, the default data is returned. * When the field is submitted, the normalized submitted data is * returned if the field is valid, null otherwise. */ public function getNormData(); /** * Returns the data transformed by the value transformer. * * @return mixed */ public function getViewData(); /** * Returns the extra data. * * @return array The submitted data which do not belong to a child */ public function getExtraData(); /** * Returns the form's configuration. * * @return FormConfigInterface The configuration. */ public function getConfig(); /** * Returns whether the form is submitted. * * @return Boolean true if the form is submitted, false otherwise */ public function isSubmitted(); /** * Returns the name by which the form is identified in forms. * * @return string The name of the form. */ public function getName(); /** * Returns the property path that the form is mapped to. * * @return \Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); /** * Adds an error to this form. * * @param FormError $error * * @return FormInterface The form instance */ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * * If the form is not submitted, this method always returns false. * * @return Boolean */ public function isValid(); /** * Returns whether the form is required to be filled out. * * If the form has a parent and the parent is not required, this method * will always return false. Otherwise the value set with setRequired() * is returned. * * @return Boolean */ public function isRequired(); /** * Returns whether this form is disabled. * * The content of a disabled form is displayed, but not allowed to be * modified. The validation of modified disabled forms should fail. * * Forms whose parents are disabled are considered disabled regardless of * their own state. * * @return Boolean */ public function isDisabled(); /** * Returns whether the form is empty. * * @return Boolean */ public function isEmpty(); /** * Returns whether the data in the different formats is synchronized. * * @return Boolean */ public function isSynchronized(); /** * Initializes the form tree. * * Should be called on the root form after constructing the tree. * * @return FormInterface The form instance. */ public function initialize(); /** * Inspects the given request and calls {@link submit()} if the form was * submitted. * * Internally, the request is forwarded to the configured * {@link RequestHandlerInterface} instance, which determines whether to * submit the form or not. * * @param mixed $request The request to handle. * * @return FormInterface The form instance. */ public function handleRequest($request = null); /** * Submits data to the form, transforms and validates it. * * @param null|string|array $submittedData The submitted data. * @param Boolean $clearMissing Whether to set fields to NULL * when they are missing in the * submitted data. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function submit($submittedData, $clearMissing = true); /** * Returns the root of the form tree. * * @return FormInterface The root of the tree */ public function getRoot(); /** * Returns whether the field is the root of the form tree. * * @return Boolean */ public function isRoot(); /** * Creates a view. * * @param FormView $parent The parent view * * @return FormView The view */ public function createView(FormView $parent = null); } PK!" FormEvent.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\Event; /** * @author Bernhard Schussek */ class FormEvent extends Event { private $form; protected $data; /** * Constructs an event. * * @param FormInterface $form The associated form * @param mixed $data The data */ public function __construct(FormInterface $form, $data) { $this->form = $form; $this->data = $data; } /** * Returns the form at the source of the event. * * @return FormInterface */ public function getForm() { return $this->form; } /** * Returns the data associated with this event. * * @return mixed */ public function getData() { return $this->data; } /** * Allows updating with some filtered data. * * @param mixed $data */ public function setData($data) { $this->data = $data; } } PK!=MMFormTypeExtensionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ interface FormTypeExtensionInterface { /** * Builds the form. * * This method is called after the extended type has built the form to * further modify it. * * @see FormTypeInterface::buildForm() * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the view. * * This method is called after the extended type has built the view to * further modify it. * * @see FormTypeInterface::buildView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the view. * * This method is called after the extended type has finished the view to * further modify it. * * @see FormTypeInterface::finishView() * * @param FormView $view The view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); /** * Overrides the default options from the extended type. * * @param OptionsResolverInterface $resolver The resolver for the options. */ public function setDefaultOptions(OptionsResolverInterface $resolver); /** * Returns the name of the type being extended. * * @return string The name of the type being extended */ public function getExtendedType(); } PK!}p  FormError.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * Wraps errors in forms * * @author Bernhard Schussek */ class FormError { /** * @var string */ private $message; /** * The template for the error message * @var string */ protected $messageTemplate; /** * The parameters that should be substituted in the message template * @var array */ protected $messageParameters; /** * The value for error message pluralization * @var integer|null */ protected $messagePluralization; /** * Constructor * * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. * * @param string $message The translated error message * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be * substituted in the message template. * @param integer|null $messagePluralization The value for error message pluralization * * @see \Symfony\Component\Translation\Translator */ public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null) { $this->message = $message; $this->messageTemplate = $messageTemplate ?: $message; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; } /** * Returns the error message * * @return string */ public function getMessage() { return $this->message; } /** * Returns the error message template * * @return string */ public function getMessageTemplate() { return $this->messageTemplate; } /** * Returns the parameters to be inserted in the message template * * @return array */ public function getMessageParameters() { return $this->messageParameters; } /** * Returns the value for error message pluralization. * * @return integer|null */ public function getMessagePluralization() { return $this->messagePluralization; } } PK! NativeRequestHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. * * @author Bernhard Schussek */ class NativeRequestHandler implements RequestHandlerInterface { /** * The allowed keys of the $_FILES array. * * @var array */ private static $fileKeys = array( 'error', 'name', 'size', 'tmp_name', 'type', ); /** * {@inheritdoc} */ public function handleRequest(FormInterface $form, $request = null) { if (null !== $request) { throw new UnexpectedTypeException($request, 'null'); } $name = $form->getName(); $method = $form->getConfig()->getMethod(); if ($method !== self::getRequestMethod()) { return; } if ('GET' === $method) { if ('' === $name) { $data = $_GET; } else { // Don't submit GET requests if the form's name does not exist // in the request if (!isset($_GET[$name])) { return; } $data = $_GET[$name]; } } else { $fixedFiles = array(); foreach ($_FILES as $name => $file) { $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); } if ('' === $name) { $params = $_POST; $files = $fixedFiles; } elseif (array_key_exists($name, $_POST) || array_key_exists($name, $fixedFiles)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; } else { // Don't submit the form if it is not present in the request return; } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } } // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } $form->submit($data, 'PATCH' !== $method); } /** * Returns the method used to submit the request to the server. * * @return string The request method. */ private static function getRequestMethod() { $method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper($_SERVER['REQUEST_METHOD']) : 'GET'; if ('POST' === $method && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); } return $method; } /** * Fixes a malformed PHP $_FILES array. * * PHP has a bug that the format of the $_FILES array differs, depending on * whether the uploaded file fields had normal field names or array-like * field names ("normal" vs. "parent[child]"). * * This method fixes the array to look like the "normal" $_FILES array. * * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * * This method is identical to {@link Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} * and should be kept as such in order to port fixes quickly and easily. * * @param array $data * * @return array */ private static function fixPhpFilesArray($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys !== $keys || !isset($data['name']) || !is_array($data['name'])) { return $data; } $files = $data; foreach (self::$fileKeys as $k) { unset($files[$k]); } foreach (array_keys($data['name']) as $key) { $files[$key] = self::fixPhpFilesArray(array( 'error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key] )); } return $files; } /** * Sets empty uploaded files to NULL in the given uploaded files array. * * @param mixed $data The file upload data. * * @return array|null Returns the stripped upload data. */ private static function stripEmptyFiles($data) { if (!is_array($data)) { return $data; } $keys = array_keys($data); sort($keys); if (self::$fileKeys === $keys) { if (UPLOAD_ERR_NO_FILE === $data['error']) { return null; } return $data; } foreach ($data as $key => $value) { $data[$key] = self::stripEmptyFiles($value); } return $data; } } PK!*8Extension/Validator/EventListener/ValidationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; /** * @author Bernhard Schussek */ class ValidationListener implements EventSubscriberInterface { private $validator; private $violationMapper; /** * {@inheritdoc} */ public static function getSubscribedEvents() { return array(FormEvents::POST_SUBMIT => 'validateForm'); } public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) { $this->validator = $validator; $this->violationMapper = $violationMapper; } /** * Validates the form and its domain object. * * @param FormEvent $event The event object */ public function validateForm(FormEvent $event) { $form = $event->getForm(); if ($form->isRoot()) { // Validate the form in group "Default" $violations = $this->validator->validate($form); foreach ($violations as $violation) { // Allow the "invalid" constraint to be put onto // non-synchronized forms $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } } } } PK!Ck)Extension/Validator/Util/ServerParams.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Util; /** * @author Bernhard Schussek */ class ServerParams { /** * Returns maximum post size in bytes. * * @return null|integer The maximum post size in bytes */ public function getPostMaxSize() { $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); if ('' === $iniMax) { return null; } $max = ltrim($iniMax, '+'); if (0 === strpos($max, '0x')) { $max = intval($max, 16); } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { $max = intval($max); } switch (substr($iniMax, -1)) { case 't': $max *= 1024; case 'g': $max *= 1024; case 'm': $max *= 1024; case 'k': $max *= 1024; } return $max; } /** * Returns the normalized "post_max_size" ini setting. * * @return string */ public function getNormalizedIniPostMaxSize() { return strtoupper(trim(ini_get('post_max_size'))); } /** * Returns the content length of the request. * * @return mixed The request content length. */ public function getContentLength() { return isset($_SERVER['CONTENT_LENGTH']) ? (int) $_SERVER['CONTENT_LENGTH'] : null; } } PK!2=[<((*Extension/Validator/ValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Validator\Constraints\Valid; /** * Extension supporting the Symfony2 Validator component in forms. * * @author Bernhard Schussek */ class ValidatorExtension extends AbstractExtension { private $validator; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; // Register the form constraints in the validator programmatically. // This functionality is required when using the Form component without // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); } public function loadTypeGuesser() { return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); } protected function loadTypeExtensions() { return array( new Type\FormTypeValidatorExtension($this->validator), new Type\RepeatedTypeValidatorExtension(), new Type\SubmitTypeValidatorExtension(), ); } } PK!}>ُ(Extension/Validator/Constraints/Form.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @author Bernhard Schussek */ class Form extends Constraint { /** * Violation code marking an invalid form. */ const ERR_INVALID = 1; /** * {@inheritdoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } } PK!-P1Extension/Validator/Constraints/FormValidator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; /** * @author Bernhard Schussek */ class FormValidator extends ConstraintValidator { /** * @var ServerParams */ private $serverParams; /** * Creates a validator with the given server parameters. * * @param ServerParams $params The server parameters. Default * parameters are created if null. */ public function __construct(ServerParams $params = null) { $this->serverParams = $params ?: new ServerParams(); } /** * {@inheritdoc} */ public function validate($form, Constraint $constraint) { if (!$form instanceof FormInterface) { return; } /* @var FormInterface $form */ $config = $form->getConfig(); if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded $groups = self::getValidationGroups($form); // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { $this->context->validate($form->getData(), 'data', $group, true); } } // Validate the data against the constraints defined // in the form $constraints = $config->getOption('constraints'); foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { $this->context->validateValue($form->getData(), $constraint, 'data', $group); // Prevent duplicate validation continue 2; } } } } else { $childrenSynchronized = true; foreach ($form as $child) { if (!$child->isSynchronized()) { $childrenSynchronized = false; break; } } // Mark the form with an error if it is not synchronized BUT all // of its children are synchronized. If any child is not // synchronized, an error is displayed there already and showing // a second error in its parent form is pointless, or worse, may // lead to duplicate errors if error bubbling is enabled on the // child. // See also https://github.com/symfony/symfony/issues/4359 if ($childrenSynchronized) { $clientDataAsString = is_scalar($form->getViewData()) ? (string) $form->getViewData() : gettype($form->getViewData()); $this->context->addViolation( $config->getOption('invalid_message'), array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), $form->getViewData(), null, Form::ERR_INVALID ); } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { $this->context->addViolation( $config->getOption('extra_fields_message'), array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), $form->getExtraData() ); } // Mark the form with an error if the uploaded size was too large $length = $this->serverParams->getContentLength(); if ($form->isRoot() && null !== $length) { $max = $this->serverParams->getPostMaxSize(); if (!empty($max) && $length > $max) { $this->context->addViolation( $config->getOption('post_max_size_message'), array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), $length ); } } } /** * Returns whether the data of a form may be walked. * * @param FormInterface $form The form to test. * * @return Boolean Whether the graph walker may walk the data. */ private static function allowDataWalking(FormInterface $form) { $data = $form->getData(); // Scalar values cannot have mapped constraints if (!is_object($data) && !is_array($data)) { return false; } // Root forms are always validated if ($form->isRoot()) { return true; } // Non-root forms are validated if validation cascading // is enabled in all ancestor forms while (null !== ($form = $form->getParent())) { if (!$form->getConfig()->getOption('cascade_validation')) { return false; } } return true; } /** * Returns the validation groups of the given form. * * @param FormInterface $form The form. * * @return array The validation groups. */ private static function getValidationGroups(FormInterface $form) { // Determine the clicked button of the complete form tree $clickedButton = null; if (method_exists($form, 'getClickedButton')) { $clickedButton = $form->getClickedButton(); } if (null !== $clickedButton) { $groups = $clickedButton->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); } } do { $groups = $form->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); } $form = $form->getParent(); } while (null !== $form); return array(Constraint::DEFAULT_GROUP); } /** * Post-processes the validation groups option for a given form. * * @param array|callable $groups The validation groups. * @param FormInterface $form The validated form. * * @return array The validation groups. */ private static function resolveValidationGroups($groups, FormInterface $form) { if (!is_string($groups) && is_callable($groups)) { $groups = call_user_func($groups, $form); } return (array) $groups; } } PK!lCt*t*,Extension/Validator/ValidatorTypeGuesser.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Constraint; class ValidatorTypeGuesser implements FormTypeGuesserInterface { private $metadataFactory; public function __construct(MetadataFactoryInterface $metadataFactory) { $this->metadataFactory = $metadataFactory; } /** * {@inheritDoc} */ public function guessType($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessTypeForConstraint($constraint); }); } /** * {@inheritDoc} */ public function guessRequired($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessRequiredForConstraint($constraint); // If we don't find any constraint telling otherwise, we can assume // that a field is not required (with LOW_CONFIDENCE) }, false); } /** * {@inheritDoc} */ public function guessMaxLength($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessMaxLengthForConstraint($constraint); }); } /** * {@inheritDoc} */ public function guessPattern($class, $property) { $guesser = $this; return $this->guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessPatternForConstraint($constraint); }); } /** * Guesses a field class name for a given constraint * * @param Constraint $constraint The constraint to guess for * * @return TypeGuess|null The guessed field class and options */ public function guessTypeForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Type': switch ($constraint->type) { case 'array': return new TypeGuess('collection', array(), Guess::MEDIUM_CONFIDENCE); case 'boolean': case 'bool': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); case 'double': case 'float': case 'numeric': case 'real': return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE); case 'integer': case 'int': case 'long': return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE); case '\DateTime': return new TypeGuess('date', array(), Guess::MEDIUM_CONFIDENCE); case 'string': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Country': return new TypeGuess('country', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Date': return new TypeGuess('date', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\DateTime': return new TypeGuess('datetime', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Email': return new TypeGuess('email', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\File': case 'Symfony\Component\Validator\Constraints\Image': return new TypeGuess('file', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Language': return new TypeGuess('language', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Locale': return new TypeGuess('locale', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Time': return new TypeGuess('time', array('input' => 'string'), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Url': return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Ip': return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Length': case 'Symfony\Component\Validator\Constraints\Regex': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Range': return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Count': return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\True': case 'Symfony\Component\Validator\Constraints\False': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); } return null; } /** * Guesses whether a field is required based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess whether the field is required */ public function guessRequiredForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\NotNull': case 'Symfony\Component\Validator\Constraints\NotBlank': case 'Symfony\Component\Validator\Constraints\True': return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } return null; } /** * Guesses a field's maximum length based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess for the maximum length */ public function guessMaxLengthForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->max)) { return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->max)) { return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE); } break; } return null; } /** * Guesses a field's pattern based on the given constraint * * @param Constraint $constraint The constraint to guess for * * @return ValueGuess|null The guess for the pattern */ public function guessPatternForConstraint(Constraint $constraint) { switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Regex': $htmlPattern = $constraint->getHtmlPattern(); if (null !== $htmlPattern) { return new ValueGuess($htmlPattern, Guess::HIGH_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE); } break; case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; } return null; } /** * Iterates over the constraints of a property, executes a constraints on * them and returns the best guess * * @param string $class The class to read the constraints from * @param string $property The property for which to find constraints * @param \Closure $closure The closure that returns a guess * for a given constraint * @param mixed $defaultValue The default value assumed if no other value * can be guessed. * * @return Guess|null The guessed value with the highest confidence */ protected function guess($class, $property, \Closure $closure, $defaultValue = null) { $guesses = array(); $classMetadata = $this->metadataFactory->getMetadataFor($class); if ($classMetadata->hasMemberMetadatas($property)) { $memberMetadatas = $classMetadata->getMemberMetadatas($property); foreach ($memberMetadatas as $memberMetadata) { $constraints = $memberMetadata->getConstraints(); foreach ($constraints as $constraint) { if ($guess = $closure($constraint)) { $guesses[] = $guess; } } } if (null !== $defaultValue) { $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); } } return Guess::getBestGuess($guesses); } } PK!ɥS=Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\PropertyAccess\PropertyPathIterator; /** * @author Bernhard Schussek */ class ViolationPathIterator extends PropertyPathIterator { public function __construct(ViolationPath $violationPath) { parent::__construct($violationPath); } public function mapsForm() { return $this->path->mapsForm($this->key()); } } PK!\T4Extension/Validator/ViolationMapper/RelativePath.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\PropertyAccess\PropertyPath; /** * @author Bernhard Schussek */ class RelativePath extends PropertyPath { /** * @var FormInterface */ private $root; /** * @param FormInterface $root * @param string $propertyPath */ public function __construct(FormInterface $root, $propertyPath) { parent::__construct($propertyPath); $this->root = $root; } /** * @return FormInterface */ public function getRoot() { return $this->root; } } PK!C_hU+U+7Extension/Validator/ViolationMapper/ViolationMapper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\PropertyAccess\PropertyPathIterator; use Symfony\Component\PropertyAccess\PropertyPathBuilder; use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ class ViolationMapper implements ViolationMapperInterface { /** * @var Boolean */ private $allowNonSynchronized; /** * {@inheritdoc} */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false) { $this->allowNonSynchronized = $allowNonSynchronized; // The scope is the currently found most specific form that // an error should be mapped to. After setting the scope, the // mapper will try to continue to find more specific matches in // the children of scope. If it cannot, the error will be // mapped to this scope. $scope = null; $violationPath = null; $relativePath = null; $match = false; // Don't create a ViolationPath instance for empty property paths if (strlen($violation->getPropertyPath()) > 0) { $violationPath = new ViolationPath($violation->getPropertyPath()); $relativePath = $this->reconstructPath($violationPath, $form); } // This case happens if the violation path is empty and thus // the violation should be mapped to the root form if (null === $violationPath) { $scope = $form; } // In general, mapping happens from the root form to the leaf forms // First, the rules of the root form are applied to determine // the subsequent descendant. The rules of this descendant are then // applied to find the next and so on, until we have found the // most specific form that matches the violation. // If any of the forms found in this process is not synchronized, // mapping is aborted. Non-synchronized forms could not reverse // transform the value entered by the user, thus any further violations // caused by the (invalid) reverse transformed value should be // ignored. if (null !== $relativePath) { // Set the scope to the root of the relative path // This root will usually be $form. If the path contains // an unmapped form though, the last unmapped form found // will be the root of the path. $scope = $relativePath->getRoot(); $it = new PropertyPathIterator($relativePath); while ($this->acceptsErrors($scope) && null !== ($child = $this->matchChild($scope, $it))) { $scope = $child; $it->next(); $match = true; } } // This case happens if an error happened in the data under a // form inheriting its parent data that does not match any of the // children of that form. if (null !== $violationPath && !$match) { // If we could not map the error to anything more specific // than the root element, map it to the innermost directly // mapped form of the violation path // e.g. "children[foo].children[bar].data.baz" // Here the innermost directly mapped child is "bar" $scope = $form; $it = new ViolationPathIterator($violationPath); // Note: acceptsErrors() will always return true for forms inheriting // their parent data, because these forms can never be non-synchronized // (they don't do any data transformation on their own) while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) { if (!$scope->has($it->current())) { // Break if we find a reference to a non-existing child break; } $scope = $scope->get($it->current()); $it->next(); } } // Follow dot rules until we have the final target $mapping = $scope->getConfig()->getOption('error_mapping'); while ($this->acceptsErrors($scope) && isset($mapping['.'])) { $dotRule = new MappingRule($scope, '.', $mapping['.']); $scope = $dotRule->getTarget(); $mapping = $scope->getConfig()->getOption('error_mapping'); } // Only add the error if the form is synchronized if ($this->acceptsErrors($scope)) { $scope->addError(new FormError( $violation->getMessage(), $violation->getMessageTemplate(), $violation->getMessageParameters(), $violation->getMessagePluralization() )); } } /** * Tries to match the beginning of the property path at the * current position against the children of the scope. * * If a matching child is found, it is returned. Otherwise * null is returned. * * @param FormInterface $form The form to search. * @param PropertyPathIteratorInterface $it The iterator at its current position. * * @return null|FormInterface The found match or null. */ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $it) { // Remember at what property path underneath "data" // we are looking. Check if there is a child with that // path, otherwise increase path by one more piece $chunk = ''; $foundChild = null; $foundAtIndex = 0; // Construct mapping rules for the given form $rules = array(); foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) { // Dot rules are considered at the very end if ('.' !== $propertyPath) { $rules[] = new MappingRule($form, $propertyPath, $targetPath); } } // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator( new InheritDataAwareIterator($form) ); // Make the path longer until we find a matching child while (true) { if (!$it->valid()) { return null; } if ($it->isIndex()) { $chunk .= '['.$it->current().']'; } else { $chunk .= ('' === $chunk ? '' : '.').$it->current(); } // Test mapping rules as long as we have any foreach ($rules as $key => $rule) { /* @var MappingRule $rule */ // Mapping rule matches completely, terminate. if (null !== ($form = $rule->match($chunk))) { return $form; } // Keep only rules that have $chunk as prefix if (!$rule->isPrefix($chunk)) { unset($rules[$key]); } } // Test children unless we already found one if (null === $foundChild) { foreach ($childIterator as $child) { /* @var FormInterface $child */ $childPath = (string) $child->getPropertyPath(); // Child found, mark as return value if ($chunk === $childPath) { $foundChild = $child; $foundAtIndex = $it->key(); } } } // Add element to the chunk $it->next(); // If we reached the end of the path or if there are no // more matching mapping rules, return the found child if (null !== $foundChild && (!$it->valid() || count($rules) === 0)) { // Reset index in case we tried to find mapping // rules further down the path $it->seek($foundAtIndex); return $foundChild; } } return null; } /** * Reconstructs a property path from a violation path and a form tree. * * @param ViolationPath $violationPath The violation path. * @param FormInterface $origin The root form of the tree. * * @return RelativePath The reconstructed path. */ private function reconstructPath(ViolationPath $violationPath, FormInterface $origin) { $propertyPathBuilder = new PropertyPathBuilder($violationPath); $it = $violationPath->getIterator(); $scope = $origin; // Remember the current index in the builder $i = 0; // Expand elements that map to a form (like "children[address]") for ($it->rewind(); $it->valid() && $it->mapsForm(); $it->next()) { if (!$scope->has($it->current())) { // Scope relates to a form that does not exist // Bail out break; } // Process child form $scope = $scope->get($it->current()); if ($scope->getConfig()->getInheritData()) { // Form inherits its parent data // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } elseif (!$scope->getConfig()->getMapped()) { // Form is not mapped // Set the form as new origin and strip everything // we have so far in the path $origin = $scope; $propertyPathBuilder->remove(0, $i + 1); $i = 0; } else { /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ $propertyPath = $scope->getPropertyPath(); if (null === $propertyPath) { // Property path of a mapped form is null // Should not happen, bail out break; } $propertyPathBuilder->replace($i, 1, $propertyPath); $i += $propertyPath->getLength(); } } $finalPath = $propertyPathBuilder->getPropertyPath(); return null !== $finalPath ? new RelativePath($origin, $finalPath) : null; } /** * @param FormInterface $form * * @return Boolean */ private function acceptsErrors(FormInterface $form) { return $this->allowNonSynchronized || $form->isSynchronized(); } } PK!kt==@Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ interface ViolationMapperInterface { /** * Maps a constraint violation to a form in the form tree under * the given form. * * @param ConstraintViolation $violation The violation to map. * @param FormInterface $form The root form of the tree * to map it to. * @param Boolean $allowNonSynchronized Whether to allow * mapping to non-synchronized forms. */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); } PK!-!!5Extension/Validator/ViolationMapper/ViolationPath.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; /** * @author Bernhard Schussek */ class ViolationPath implements \IteratorAggregate, PropertyPathInterface { /** * @var array */ private $elements = array(); /** * @var array */ private $isIndex = array(); /** * @var array */ private $mapsForm = array(); /** * @var string */ private $pathAsString = ''; /** * @var integer */ private $length = 0; /** * Creates a new violation path from a string. * * @param string $violationPath The property path of a {@link ConstraintViolation} * object. */ public function __construct($violationPath) { $path = new PropertyPath($violationPath); $elements = $path->getElements(); $data = false; for ($i = 0, $l = count($elements); $i < $l; ++$i) { if (!$data) { // The element "data" has not yet been passed if ('children' === $elements[$i] && $path->isProperty($i)) { // Skip element "children" ++$i; // Next element must exist and must be an index // Otherwise consider this the end of the path if ($i >= $l || !$path->isIndex($i)) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = true; $this->mapsForm[] = true; } elseif ('data' === $elements[$i] && $path->isProperty($i)) { // Skip element "data" ++$i; // End of path if ($i >= $l) { break; } $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; $data = true; } else { // Neither "children" nor "data" property found // Consider this the end of the path break; } } else { // Already after the "data" element // Pick everything as is $this->elements[] = $elements[$i]; $this->isIndex[] = $path->isIndex($i); $this->mapsForm[] = false; } } $this->length = count($this->elements); $this->buildString(); } /** * {@inheritdoc} */ public function __toString() { return $this->pathAsString; } /** * {@inheritdoc} */ public function getLength() { return $this->length; } /** * {@inheritdoc} */ public function getParent() { if ($this->length <= 1) { return null; } $parent = clone $this; --$parent->length; array_pop($parent->elements); array_pop($parent->isIndex); array_pop($parent->mapsForm); $parent->buildString(); return $parent; } /** * {@inheritdoc} */ public function getElements() { return $this->elements; } /** * {@inheritdoc} */ public function getElement($index) { if (!isset($this->elements[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->elements[$index]; } /** * {@inheritdoc} */ public function isProperty($index) { if (!isset($this->isIndex[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return !$this->isIndex[$index]; } /** * {@inheritdoc} */ public function isIndex($index) { if (!isset($this->isIndex[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->isIndex[$index]; } /** * Returns whether an element maps directly to a form. * * Consider the following violation path: * * * children[address].children[office].data.street * * * In this example, "address" and "office" map to forms, while * "street does not. * * @param integer $index The element index. * * @return Boolean Whether the element maps to a form. * * @throws OutOfBoundsException If the offset is invalid. */ public function mapsForm($index) { if (!isset($this->mapsForm[$index])) { throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->mapsForm[$index]; } /** * Returns a new iterator for this path * * @return ViolationPathIterator */ public function getIterator() { return new ViolationPathIterator($this); } /** * Builds the string representation from the elements. */ private function buildString() { $this->pathAsString = ''; $data = false; foreach ($this->elements as $index => $element) { if ($this->mapsForm[$index]) { $this->pathAsString .= ".children[$element]"; } elseif (!$data) { $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element"); $data = true; } else { $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element"; } } if ('' !== $this->pathAsString) { // remove leading dot $this->pathAsString = substr($this->pathAsString, 1); } } } PK!f 3Extension/Validator/ViolationMapper/MappingRule.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Exception\ErrorMappingException; /** * @author Bernhard Schussek */ class MappingRule { /** * @var FormInterface */ private $origin; /** * @var string */ private $propertyPath; /** * @var string */ private $targetPath; public function __construct(FormInterface $origin, $propertyPath, $targetPath) { $this->origin = $origin; $this->propertyPath = $propertyPath; $this->targetPath = $targetPath; } /** * @return FormInterface */ public function getOrigin() { return $this->origin; } /** * Matches a property path against the rule path. * * If the rule matches, the form mapped by the rule is returned. * Otherwise this method returns false. * * @param string $propertyPath The property path to match against the rule. * * @return null|FormInterface The mapped form or null. */ public function match($propertyPath) { if ($propertyPath === (string) $this->propertyPath) { return $this->getTarget(); } return null; } /** * Matches a property path against a prefix of the rule path. * * @param string $propertyPath The property path to match against the rule. * * @return Boolean Whether the property path is a prefix of the rule or not. */ public function isPrefix($propertyPath) { $length = strlen($propertyPath); $prefix = substr($this->propertyPath, 0, $length); $next = isset($this->propertyPath[$length]) ? $this->propertyPath[$length] : null; return $prefix === $propertyPath && ('[' === $next || '.' === $next); } /** * @return FormInterface * * @throws ErrorMappingException */ public function getTarget() { $childNames = explode('.', $this->targetPath); $target = $this->origin; foreach ($childNames as $childName) { if (!$target->has($childName)) { throw new ErrorMappingException(sprintf('The child "%s" of "%s" mapped by the rule "%s" in "%s" does not exist.', $childName, $target->getName(), $this->targetPath, $this->origin->getName())); } $target = $target->get($childName); } return $target; } } PK!3Extension/Validator/Type/BaseValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * Encapsulates common logic of {@link FormTypeValidatorExtension} and * {@link SubmitTypeValidatorExtension}. * * @author Bernhard Schussek */ abstract class BaseValidatorExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Make sure that validation groups end up as null, closure or array $validationGroupsNormalizer = function (Options $options, $groups) { if (false === $groups) { return array(); } if (empty($groups)) { return null; } if (is_callable($groups)) { return $groups; } return (array) $groups; }; $resolver->setDefaults(array( 'validation_groups' => null, )); $resolver->setNormalizers(array( 'validation_groups' => $validationGroupsNormalizer, )); } } PK!eBR 7Extension/Validator/Type/FormTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class FormTypeValidatorExtension extends BaseValidatorExtension { /** * @var ValidatorInterface */ private $validator; /** * @var ViolationMapper */ private $violationMapper; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; $this->violationMapper = new ViolationMapper(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber(new ValidationListener($this->validator, $this->violationMapper)); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); // Constraint should always be converted to an array $constraintsNormalizer = function (Options $options, $constraints) { return is_object($constraints) ? array($constraints) : (array) $constraints; }; $resolver->setDefaults(array( 'error_mapping' => array(), 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'extra_fields_message' => 'This form should not contain extra fields.', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); $resolver->setNormalizers(array( 'constraints' => $constraintsNormalizer, )); } /** * {@inheritdoc} */ public function getExtendedType() { return 'form'; } } PK!͚>@@;Extension/Validator/Type/RepeatedTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class RepeatedTypeValidatorExtension extends AbstractTypeExtension { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Map errors to the first field $errorMapping = function (Options $options) { return array('.' => $options['first_name']); }; $resolver->setDefaults(array( 'error_mapping' => $errorMapping, )); } /** * {@inheritdoc} */ public function getExtendedType() { return 'repeated'; } } PK!19Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Validator\Type; /** * @author Bernhard Schussek */ class SubmitTypeValidatorExtension extends BaseValidatorExtension { /** * {@inheritdoc} */ public function getExtendedType() { return 'submit'; } } PK!,QQ,Extension/Templating/TemplatingExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Templating\PhpEngine; use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper; /** * Integrates the Templating component with the Form library. * * @author Bernhard Schussek */ class TemplatingExtension extends AbstractExtension { public function __construct(PhpEngine $engine, $csrfTokenManager = null, array $defaultThemes = array()) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $engine->addHelpers(array( new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenManager)) )); } } PK!զY1Extension/Templating/TemplatingRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\FormView; use Symfony\Component\Templating\EngineInterface; /** * @author Bernhard Schussek */ class TemplatingRendererEngine extends AbstractRendererEngine { /** * @var EngineInterface */ private $engine; public function __construct(EngineInterface $engine, array $defaultThemes = array()) { parent::__construct($defaultThemes); $this->engine = $engine; } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()) { return trim($this->engine->render($resource, $variables)); } /** * Loads the cache with the resource for a given block name. * * This implementation tries to load as few blocks as possible, since each block * is represented by a template on the file system. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { // Recursively try to find the block in the themes assigned to $view, // then of its parent form, then of the parent form of the parent and so on. // When the root form is reached in this recursion, also the default // themes are taken into account. // Check each theme whether it contains the searched block if (isset($this->themes[$cacheKey])) { for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->themes[$cacheKey][$i])) { return true; } } } // Check the default themes once we reach the root form without success if (!$view->parent) { for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) { return true; } } } // If we did not find anything in the themes of the current view, proceed // with the themes of the parent view if ($view->parent) { $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$parentCacheKey][$blockName])) { $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName); } // If a template exists in the parent themes, cache that template // for the current theme as well to speed up further accesses if ($this->resources[$parentCacheKey][$blockName]) { $this->resources[$cacheKey][$blockName] = $this->resources[$parentCacheKey][$blockName]; return true; } } // Cache that we didn't find anything to speed up further accesses $this->resources[$cacheKey][$blockName] = false; return false; } /** * Tries to load the resource for a block from a theme. * * @param string $cacheKey The cache key for storing the resource. * @param string $blockName The name of the block to load a resource for. * @param mixed $theme The theme to load the block from. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceFromTheme($cacheKey, $blockName, $theme) { if ($this->engine->exists($templateName = $theme.':'.$blockName.'.html.php')) { $this->resources[$cacheKey][$blockName] = $templateName; return true; } return false; } } PK!䋧 >Extension/HttpFoundation/EventListener/BindRequestListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; /** * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the * Request instance to {@link Form::handleRequest()} instead. */ class BindRequestListener implements EventSubscriberInterface { public static function getSubscribedEvents() { // High priority in order to supersede other listeners return array(FormEvents::PRE_BIND => array('preBind', 128)); } public function preBind(FormEvent $event) { $form = $event->getForm(); /* @var Request $request */ $request = $event->getData(); // Only proceed if we actually deal with a Request if (!$request instanceof Request) { return; } // Uncomment this as soon as the deprecation note should be shown // trigger_error('Passing a Request instance to Form::submit() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; // Store the bound data in case of a post request switch ($request->getMethod()) { case 'POST': case 'PUT': case 'DELETE': case 'PATCH': if ('' === $name) { // Form bound without name $params = $request->request->all(); $files = $request->files->all(); } else { $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } break; case 'GET': $data = '' === $name ? $request->query->all() : $request->query->get($name, $default); break; default: throw new LogicException(sprintf( 'The request method "%s" is not supported', $request->getMethod() )); } $event->setData($data); } } PK!j= = 9Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\HttpFoundation\Request; /** * A request processor using the {@link Request} class of the HttpFoundation * component. * * @author Bernhard Schussek */ class HttpFoundationRequestHandler implements RequestHandlerInterface { /** * {@inheritdoc} */ public function handleRequest(FormInterface $form, $request = null) { if (!$request instanceof Request) { throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); } $name = $form->getName(); $method = $form->getConfig()->getMethod(); if ($method !== $request->getMethod()) { return; } if ('GET' === $method) { if ('' === $name) { $data = $request->query->all(); } else { // Don't submit GET requests if the form's name does not exist // in the request if (!$request->query->has($name)) { return; } $data = $request->query->get($name); } } else { if ('' === $name) { $params = $request->request->all(); $files = $request->files->all(); } elseif ($request->request->has($name) || $request->files->has($name)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } else { // Don't submit the form if it is not present in the request return; } if (is_array($params) && is_array($files)) { $data = array_replace_recursive($params, $files); } else { $data = $params ?: $files; } } // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } $form->submit($data, 'PATCH' !== $method); } } PK!Q4Extension/HttpFoundation/HttpFoundationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\AbstractExtension; /** * Integrates the HttpFoundation component with the Form library. * * @author Bernhard Schussek */ class HttpFoundationExtension extends AbstractExtension { protected function loadTypeExtensions() { return array( new Type\FormTypeHttpFoundationExtension(), ); } } PK!PffAExtension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\HttpFoundation\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormBuilderInterface; /** * @author Bernhard Schussek */ class FormTypeHttpFoundationExtension extends AbstractTypeExtension { /** * @var BindRequestListener */ private $listener; /** * @var HttpFoundationRequestHandler */ private $requestHandler; public function __construct() { $this->listener = new BindRequestListener(); $this->requestHandler = new HttpFoundationRequestHandler(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); $builder->setRequestHandler($this->requestHandler); } /** * {@inheritdoc} */ public function getExtendedType() { return 'form'; } } PK!"q Extension/Csrf/CsrfExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * This extension protects forms by using a CSRF token. * * @author Bernhard Schussek */ class CsrfExtension extends AbstractExtension { /** * @var CsrfTokenManagerInterface */ private $tokenManager; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * Constructor. * * @param CsrfTokenManagerInterface $tokenManager The CSRF token manager * @param TranslatorInterface $translator The translator for translating error messages * @param null|string $translationDomain The translation domain for translating */ public function __construct($tokenManager, TranslatorInterface $translator = null, $translationDomain = null) { if ($tokenManager instanceof CsrfProviderInterface) { $tokenManager = new CsrfProviderAdapter($tokenManager); } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->tokenManager = $tokenManager; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * {@inheritDoc} */ protected function loadTypeExtensions() { return array( new Type\FormTypeCsrfExtension($this->tokenManager, true, '_token', $this->translator, $this->translationDomain), ); } } PK!C3Extension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** * Default implementation of CsrfProviderInterface. * * This provider uses the session ID returned by session_id() as well as a * user-defined secret value to secure the CSRF token. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage} * instead. */ class DefaultCsrfProvider implements CsrfProviderInterface { /** * A secret value used for generating the CSRF token * @var string */ protected $secret; /** * Initializes the provider with a secret value * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. * * @param string $secret A secret value included in the CSRF token */ public function __construct($secret) { $this->secret = $secret; } /** * {@inheritDoc} */ public function generateCsrfToken($intention) { return sha1($this->secret.$intention.$this->getSessionId()); } /** * {@inheritDoc} */ public function isCsrfTokenValid($intention, $token) { return $token === $this->generateCsrfToken($intention); } /** * Returns the ID of the user session. * * Automatically starts the session if necessary. * * @return string The session ID */ protected function getSessionId() { if (version_compare(PHP_VERSION, '5.4', '>=')) { if (PHP_SESSION_NONE === session_status()) { session_start(); } } elseif (!session_id()) { session_start(); } return session_id(); } } PK![^3Extension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\HttpFoundation\Session\Session; /** * This provider uses a Symfony2 Session object to retrieve the user's * session ID. * * @see DefaultCsrfProvider * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage} * instead. */ class SessionCsrfProvider extends DefaultCsrfProvider { /** * The user session from which the session ID is returned * @var Session */ protected $session; /** * Initializes the provider with a Session object and a secret value. * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. * * @param Session $session The user session * @param string $secret A secret value included in the CSRF token */ public function __construct(Session $session, $secret) { parent::__construct($secret); $this->session = $session; } /** * {@inheritdoc} */ protected function getSessionId() { $this->session->start(); return $this->session->getId(); } } PK!%G5Extension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** * Marks classes able to provide CSRF protection * * You can generate a CSRF token by using the method generateCsrfToken(). To * this method you should pass a value that is unique to the page that should * be secured against CSRF attacks. This value doesn't necessarily have to be * secret. Implementations of this interface are responsible for adding more * secret information. * * If you want to secure a form submission against CSRF attacks, you could * supply an "intention" string. This way you make sure that the form can only * be submitted to pages that are designed to handle the form, that is, that use * the same intention string to validate the CSRF token with isCsrfTokenValid(). * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use * {@link \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface} * instead. */ interface CsrfProviderInterface { /** * Generates a CSRF token for a page of your application. * * @param string $intention Some value that identifies the action intention * (i.e. "authenticate"). Doesn't have to be a secret value. * * @return string The generated token */ public function generateCsrfToken($intention); /** * Validates a CSRF token. * * @param string $intention The intention used when generating the CSRF token * @param string $token The token supplied by the browser * * @return Boolean Whether the token supplied by the browser is correct */ public function isCsrfTokenValid($intention, $token); } PK!3Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Adapter for using old CSRF providers where the new {@link CsrfTokenManagerInterface} * is expected. * * @since 2.4 * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ class CsrfProviderAdapter implements CsrfTokenManagerInterface { /** * @var CsrfProviderInterface */ private $csrfProvider; public function __construct(CsrfProviderInterface $csrfProvider) { $this->csrfProvider = $csrfProvider; } public function getCsrfProvider() { return $this->csrfProvider; } /** * {@inheritdoc} */ public function getToken($tokenId) { return new CsrfToken($tokenId, $this->csrfProvider->generateCsrfToken($tokenId)); } /** * {@inheritdoc} */ public function refreshToken($tokenId) { throw new BadMethodCallException('Not supported'); } /** * {@inheritdoc} */ public function removeToken($tokenId) { throw new BadMethodCallException('Not supported'); } /** * {@inheritdoc} */ public function isTokenValid(CsrfToken $token) { return $this->csrfProvider->isCsrfTokenValid($token->getId(), $token->getValue()); } } PK!R'WTT7Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Adapter for using the new token generator with the old interface. * * @since 2.4 * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ class CsrfTokenManagerAdapter implements CsrfProviderInterface { /** * @var CsrfTokenManagerInterface */ private $tokenManager; public function __construct(CsrfTokenManagerInterface $tokenManager) { $this->tokenManager = $tokenManager; } public function getTokenManager() { return $this->tokenManager; } /** * {@inheritdoc} */ public function generateCsrfToken($intention) { return $this->tokenManager->getToken($intention)->getValue(); } /** * {@inheritdoc} */ public function isCsrfTokenValid($intention, $token) { return $this->tokenManager->isTokenValid(new CsrfToken($intention, $token)); } } PK!?oo7Extension/Csrf/EventListener/CsrfValidationListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class CsrfValidationListener implements EventSubscriberInterface { /** * The name of the CSRF field * @var string */ private $fieldName; /** * The generator for CSRF tokens * @var CsrfTokenManagerInterface */ private $tokenManager; /** * A text mentioning the tokenId of the CSRF token * * Validation of the token will only succeed if it was generated in the * same session and with the same tokenId. * * @var string */ private $tokenId; /** * The message displayed in case of an error. * @var string */ private $errorMessage; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; public static function getSubscribedEvents() { return array( FormEvents::PRE_SUBMIT => 'preSubmit', ); } public function __construct($fieldName, $tokenManager, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) { if ($tokenManager instanceof CsrfProviderInterface) { $tokenManager = new CsrfProviderAdapter($tokenManager); } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->fieldName = $fieldName; $this->tokenManager = $tokenManager; $this->tokenId = $tokenId; $this->errorMessage = $errorMessage; $this->translator = $translator; $this->translationDomain = $translationDomain; } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if ($form->isRoot() && $form->getConfig()->getOption('compound')) { if (!isset($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) { $errorMessage = $this->errorMessage; if (null !== $this->translator) { $errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain); } $form->addError(new FormError($errorMessage)); } if (is_array($data)) { unset($data[$this->fieldName]); } } $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } } PK! f-Extension/Csrf/Type/FormTypeCsrfExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class FormTypeCsrfExtension extends AbstractTypeExtension { /** * @var CsrfTokenManagerInterface */ private $defaultTokenManager; /** * @var Boolean */ private $defaultEnabled; /** * @var string */ private $defaultFieldName; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; public function __construct($defaultTokenManager, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) { if ($defaultTokenManager instanceof CsrfProviderInterface) { $defaultTokenManager = new CsrfProviderAdapter($defaultTokenManager); } elseif (!$defaultTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($defaultTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } $this->defaultTokenManager = $defaultTokenManager; $this->defaultEnabled = $defaultEnabled; $this->defaultFieldName = $defaultFieldName; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * Adds a CSRF field to the form when the CSRF protection is enabled. * * @param FormBuilderInterface $builder The form builder * @param array $options The options */ public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['csrf_protection']) { return; } $builder ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], $options['csrf_token_manager'], $options['csrf_token_id'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType())), $options['csrf_message'], $this->translator, $this->translationDomain )) ; } /** * Adds a CSRF field to the root form view. * * @param FormView $view The form view * @param FormInterface $form The form * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getFormFactory(); $tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: get_class($form->getConfig()->getType()->getInnerType())); $data = (string) $options['csrf_token_manager']->getToken($tokenId); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, )); $view->children[$options['csrf_field_name']] = $csrfForm->createView($view); } } /** * {@inheritDoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { // BC clause for the "intention" option $csrfTokenId = function (Options $options) { return $options['intention']; }; // BC clause for the "csrf_provider" option $csrfTokenManager = function (Options $options) { return $options['csrf_provider'] instanceof CsrfTokenManagerAdapter ? $options['csrf_provider']->getTokenManager() : new CsrfProviderAdapter($options['csrf_provider']); }; $resolver->setDefaults(array( 'csrf_protection' => $this->defaultEnabled, 'csrf_field_name' => $this->defaultFieldName, 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => $csrfTokenManager, 'csrf_token_id' => $csrfTokenId, 'csrf_provider' => new CsrfTokenManagerAdapter($this->defaultTokenManager), 'intention' => null, )); } /** * {@inheritDoc} */ public function getExtendedType() { return 'form'; } } PK!CW Extension/Core/CoreExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\PropertyAccess\PropertyAccess; /** * Represents the main form extension, which loads the core functionality. * * @author Bernhard Schussek */ class CoreExtension extends AbstractExtension { protected function loadTypes() { return array( new Type\FormType(PropertyAccess::createPropertyAccessor()), new Type\BirthdayType(), new Type\CheckboxType(), new Type\ChoiceType(), new Type\CollectionType(), new Type\CountryType(), new Type\DateType(), new Type\DateTimeType(), new Type\EmailType(), new Type\HiddenType(), new Type\IntegerType(), new Type\LanguageType(), new Type\LocaleType(), new Type\MoneyType(), new Type\NumberType(), new Type\PasswordType(), new Type\PercentType(), new Type\RadioType(), new Type\RepeatedType(), new Type\SearchType(), new Type\TextareaType(), new Type\TextType(), new Type\TimeType(), new Type\TimezoneType(), new Type\UrlType(), new Type\FileType(), new Type\ButtonType(), new Type\SubmitType(), new Type\ResetType(), new Type\CurrencyType(), ); } } PK!:AA-Extension/Core/EventListener/TrimListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Trims string data * * @author Bernhard Schussek */ class TrimListener implements EventSubscriberInterface { public function preSubmit(FormEvent $event) { $data = $event->getData(); if (!is_string($data)) { return; } if (null !== $result = @preg_replace('/^[\pZ\p{Cc}]+|[\pZ\p{Cc}]+$/u', '', $data)) { $event->setData($result); } else { $event->setData(trim($data)); } } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK!õe8Extension/Core/EventListener/MergeCollectionListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class MergeCollectionListener implements EventSubscriberInterface { /** * Whether elements may be added to the collection * @var Boolean */ private $allowAdd; /** * Whether elements may be removed from the collection * @var Boolean */ private $allowDelete; /** * Creates a new listener. * * @param Boolean $allowAdd Whether values might be added to the * collection. * @param Boolean $allowDelete Whether values might be removed from the * collection. */ public function __construct($allowAdd = false, $allowDelete = false) { $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; } public static function getSubscribedEvents() { return array( FormEvents::SUBMIT => 'onSubmit', ); } public function onSubmit(FormEvent $event) { $dataToMergeInto = $event->getForm()->getNormData(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } if (null !== $dataToMergeInto && !is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) { throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)'); } // If we are not allowed to change anything, return immediately if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) { $event->setData($dataToMergeInto); return; } if (!$dataToMergeInto) { // No original data was set. Set it if allowed if ($this->allowAdd) { $dataToMergeInto = $data; } } else { // Calculate delta $itemsToAdd = is_object($data) ? clone $data : $data; $itemsToDelete = array(); foreach ($dataToMergeInto as $beforeKey => $beforeItem) { foreach ($data as $afterKey => $afterItem) { if ($afterItem === $beforeItem) { // Item found, next original item unset($itemsToAdd[$afterKey]); continue 2; } } // Item not found, remember for deletion $itemsToDelete[] = $beforeKey; } // Remove deleted items before adding to free keys that are to be // replaced if ($this->allowDelete) { foreach ($itemsToDelete as $key) { unset($dataToMergeInto[$key]); } } // Add remaining items if ($this->allowAdd) { foreach ($itemsToAdd as $key => $item) { if (!isset($dataToMergeInto[$key])) { $dataToMergeInto[$key] = $item; } else { $dataToMergeInto[] = $item; } } } } $event->setData($dataToMergeInto); } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } } PK!>Q?7Extension/Core/EventListener/FixUrlProtocolListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Adds a protocol to a URL if it doesn't already have one. * * @author Bernhard Schussek */ class FixUrlProtocolListener implements EventSubscriberInterface { private $defaultProtocol; public function __construct($defaultProtocol = 'http') { $this->defaultProtocol = $defaultProtocol; } public function onSubmit(FormEvent $event) { $data = $event->getData(); if ($this->defaultProtocol && $data && !preg_match('~^\w+://~', $data)) { $event->setData($this->defaultProtocol.'://'.$data); } } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::SUBMIT => 'onSubmit'); } } PK!b 9Extension/Core/EventListener/FixCheckboxInputListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * Takes care of converting the input from a list of checkboxes to a correctly * indexed array. * * @author Bernhard Schussek */ class FixCheckboxInputListener implements EventSubscriberInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } public function preSubmit(FormEvent $event) { $data = $event->getData(); if (is_array($data)) { // Flip the submitted values for faster lookup // It's better to flip this array than $existingValues because // $submittedValues is generally smaller. $submittedValues = array_flip($data); // Since expanded choice fields are completely loaded anyway, we // can just as well get the values again without losing performance. $existingValues = $this->choiceList->getValues(); // Clear the data array and fill it with correct indices $data = array(); foreach ($existingValues as $index => $value) { if (isset($submittedValues[$value])) { // Value was submitted $data[$index] = $value; unset($submittedValues[$value]); } } if (count($submittedValues) > 0) { throw new TransformationFailedException(sprintf( 'The following choices were not found: "%s"', implode('", "', array_keys($submittedValues)) )); } } elseif ('' === $data || null === $data) { // Empty values are always accepted. $data = array(); } // Else leave the data unchanged to provoke an error during submission $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK!\//3Extension/Core/EventListener/ResizeFormListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Resize a collection form element based on the data sent from the client. * * @author Bernhard Schussek */ class ResizeFormListener implements EventSubscriberInterface { /** * @var string */ protected $type; /** * @var array */ protected $options; /** * Whether children could be added to the group * @var Boolean */ protected $allowAdd; /** * Whether children could be removed from the group * @var Boolean */ protected $allowDelete; public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false) { $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; $this->options = $options; } public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', FormEvents::PRE_SUBMIT => 'preSubmit', // (MergeCollectionListener, MergeDoctrineCollectionListener) FormEvents::SUBMIT => array('onSubmit', 50), ); } public function preSetData(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // First remove all rows foreach ($form as $name => $child) { $form->remove($name); } // Then add all rows again in the correct order foreach ($data as $name => $value) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data || '' === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // Remove all empty rows if ($this->allowDelete) { foreach ($form as $name => $child) { if (!isset($data[$name])) { $form->remove($name); } } } // Add all additional rows if ($this->allowAdd) { foreach ($data as $name => $value) { if (!$form->has($name)) { $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } } } } public function onSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $data = array(); } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { $toDelete = array(); foreach ($data as $name => $child) { if (!$form->has($name)) { $toDelete[] = $name; } } foreach ($toDelete as $name) { unset($data[$name]); } } $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } /** * Alias of {@link onSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link onSubmit()} instead. */ public function onBind(FormEvent $event) { $this->onSubmit($event); } } PK!?D6Extension/Core/EventListener/FixRadioInputListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\EventListener; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * Takes care of converting the input from a single radio button * to an array. * * @author Bernhard Schussek */ class FixRadioInputListener implements EventSubscriberInterface { private $choiceList; private $placeholderPresent; /** * Constructor. * * @param ChoiceListInterface $choiceList * @param Boolean $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; $this->placeholderPresent = $placeholderPresent; } public function preSubmit(FormEvent $event) { $data = $event->getData(); // Since expanded choice fields are completely loaded anyway, we // can just as well get the values again without losing performance. $existingValues = $this->choiceList->getValues(); if (false !== ($index = array_search($data, $existingValues, true))) { $data = array($index => $data); } elseif ('' === $data || null === $data) { // Empty values are always accepted. $data = $this->placeholderPresent ? array('placeholder' => '') : array(); } // Else leave the data unchanged to provoke an error during submission $event->setData($data); } /** * Alias of {@link preSubmit()}. * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link preSubmit()} instead. */ public function preBind(FormEvent $event) { $this->preSubmit($event); } public static function getSubscribedEvents() { return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } PK!jю.Extension/Core/ChoiceList/SimpleChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; /** * A choice list for choices of type string or integer. * * Choices and their associated labels can be passed in a single array. Since * choices are passed as array keys, only strings or integer choices are * allowed. Choices may also be given as hierarchy of unlimited depth by * creating nested arrays. The title of the sub-hierarchy can be stored in the * array key pointing to the nested array. * * * $choiceList = new SimpleChoiceList(array( * 'creditcard' => 'Credit card payment', * 'cash' => 'Cash payment', * )); * * * @author Bernhard Schussek */ class SimpleChoiceList extends ChoiceList { /** * Creates a new simple choice list. * * @param array $choices The array of choices with the choices as keys and * the labels as values. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy is stored * in the array key pointing to the nested array. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. */ public function __construct(array $choices, array $preferredChoices = array()) { // Flip preferred choices to speed up lookup parent::__construct($choices, $choices, array_flip($preferredChoices)); } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { $values = $this->fixValues($values); // The values are identical to the choices, so we can just return them // to improve performance a little bit return $this->fixChoices(array_intersect($values, $this->getValues())); } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { $choices = $this->fixChoices($choices); // The choices are identical to the values, so we can just return them // to improve performance a little bit return $this->fixValues(array_intersect($choices, $this->getValues())); } /** * Recursively adds the given choices to the list. * * Takes care of splitting the single $choices array passed in the * constructor into choices and labels. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array|\Traversable $choices The list of choices. * @param array $labels Ignored. * @param array $preferredChoices The preferred choices. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { // Add choices to the nested buckets foreach ($choices as $choice => $label) { if (is_array($label)) { // Don't do the work if the array is empty if (count($label) > 0) { $this->addChoiceGroup( $choice, $bucketForPreferred, $bucketForRemaining, $label, $label, $preferredChoices ); } } else { $this->addChoice( $bucketForPreferred, $bucketForRemaining, $choice, $label, $preferredChoices ); } } } /** * Returns whether the given choice should be preferred judging by the * given array of preferred choices. * * Optimized for performance by treating the preferred choices as array * where choices are stored in the keys. * * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * * @return Boolean Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { // Optimize performance over the default implementation return isset($preferredChoices[$choice]); } /** * Converts the choice to a valid PHP array key. * * @param mixed $choice The choice * * @return string|integer A valid PHP array key */ protected function fixChoice($choice) { return $this->fixIndex($choice); } /** * {@inheritdoc} */ protected function fixChoices(array $choices) { return $this->fixIndices($choices); } /** * {@inheritdoc} */ protected function createValue($choice) { // Choices are guaranteed to be unique and scalar, so we can simply // convert them to strings return (string) $choice; } } PK! ##.Extension/Core/ChoiceList/ObjectChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\StringCastException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A choice list for object choices. * * Supports generation of choice labels, choice groups and choice values * by calling getters of the object (or associated objects). * * * $choices = array($user1, $user2); * * // call getName() to determine the choice labels * $choiceList = new ObjectChoiceList($choices, 'name'); * * * @author Bernhard Schussek */ class ObjectChoiceList extends ChoiceList { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * The property path used to obtain the choice label. * * @var PropertyPath */ private $labelPath; /** * The property path used for object grouping. * * @var PropertyPath */ private $groupPath; /** * The property path used to obtain the choice value. * * @var PropertyPath */ private $valuePath; /** * Creates a new object choice list. * * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy can be * stored in the array key pointing to the nested * array. The topmost level of the hierarchy may also * be a \Traversable. * @param string $labelPath A property path pointing to the property used * for the choice labels. The value is obtained * by calling the getter on the object. If the * path is NULL, the object's __toString() method * is used instead. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. * @param string $valuePath A property path pointing to the property used * for the choice values. If not given, integers * are generated instead. * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. */ public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null; $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null; $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null; parent::__construct($choices, array(), $preferredChoices); } /** * Initializes the list with choices. * * Safe to be called multiple times. The list is cleared on every call. * * @param array|\Traversable $choices The choices to write into the list. * @param array $labels Ignored. * @param array $preferredChoices The choices to display with priority. * * @throws InvalidArgumentException When passing a hierarchy of choices and using * the "groupPath" option at the same time. */ protected function initialize($choices, array $labels, array $preferredChoices) { if (null !== $this->groupPath) { $groupedChoices = array(); foreach ($choices as $i => $choice) { if (is_array($choice)) { throw new InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.'); } try { $group = $this->propertyAccessor->getValue($choice, $this->groupPath); } catch (NoSuchPropertyException $e) { // Don't group items whose group property does not exist // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf $group = null; } if (null === $group) { $groupedChoices[$i] = $choice; } else { $groupName = (string) $group; if (!isset($groupedChoices[$groupName])) { $groupedChoices[$groupName] = array(); } $groupedChoices[$groupName][$i] = $choice; } } $choices = $groupedChoices; } $labels = array(); $this->extractLabels($choices, $labels); parent::initialize($choices, $labels, $preferredChoices); } /** * Creates a new unique value for this choice. * * If a property path for the value was given at object creation, * the getter behind that path is now called to obtain a new value. * Otherwise a new integer is generated. * * @param mixed $choice The choice to create a value for * * @return integer|string A unique value without character limitations. */ protected function createValue($choice) { if ($this->valuePath) { return (string) $this->propertyAccessor->getValue($choice, $this->valuePath); } return parent::createValue($choice); } private function extractLabels($choices, array &$labels) { foreach ($choices as $i => $choice) { if (is_array($choice)) { $labels[$i] = array(); $this->extractLabels($choice, $labels[$i]); } elseif ($this->labelPath) { $labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath); } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { throw new StringCastException(sprintf('A "__toString()" method was not found on the objects of type "%s" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.', get_class($choice))); } } } } PK!l_R(1Extension/Core/ChoiceList/ChoiceListInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; /** * Contains choices that can be selected in a form field. * * Each choice has three different properties: * * - Choice: The choice that should be returned to the application by the * choice field. Can be any scalar value or an object, but no * array. * - Label: A text representing the choice that is displayed to the user. * - Value: A uniquely identifying value that can contain arbitrary * characters, but no arrays or objects. This value is displayed * in the HTML "value" attribute. * * @author Bernhard Schussek */ interface ChoiceListInterface { /** * Returns the list of choices * * @return array The choices with their indices as keys */ public function getChoices(); /** * Returns the values for the choices * * @return array The values with the corresponding choice indices as keys */ public function getValues(); /** * Returns the choice views of the preferred choices as nested array with * the choice groups as top-level keys. * * Example: * * * array( * 'Group 1' => array( * 10 => ChoiceView object, * 20 => ChoiceView object, * ), * 'Group 2' => array( * 30 => ChoiceView object, * ), * ) * * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels */ public function getPreferredViews(); /** * Returns the choice views of the choices that are not preferred as nested * array with the choice groups as top-level keys. * * Example: * * * array( * 'Group 1' => array( * 10 => ChoiceView object, * 20 => ChoiceView object, * ), * 'Group 2' => array( * 30 => ChoiceView object, * ), * ) * * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels * * @see getPreferredValues */ public function getRemainingViews(); /** * Returns the choices corresponding to the given values. * * The choices can have any data type. * * The choices must be returned with the same keys and in the same order * as the corresponding values in the given array. * * @param array $values An array of choice values. Not existing values in * this array are ignored * * @return array An array of choices with ascending, 0-based numeric keys */ public function getChoicesForValues(array $values); /** * Returns the values corresponding to the given choices. * * The values must be strings. * * The values must be returned with the same keys and in the same order * as the corresponding choices in the given array. * * @param array $choices An array of choices. Not existing choices in this * array are ignored * * @return array An array of choice values with ascending, 0-based numeric * keys */ public function getValuesForChoices(array $choices); /** * Returns the indices corresponding to the given choices. * * The indices must be positive integers or strings accepted by * {@link FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * * The indices must be returned with the same keys and in the same order * as the corresponding choices in the given array. * * @param array $choices An array of choices. Not existing choices in this * array are ignored * * @return array An array of indices with ascending, 0-based numeric keys * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices); /** * Returns the indices corresponding to the given values. * * The indices must be positive integers or strings accepted by * {@link FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * * The indices must be returned with the same keys and in the same order * as the corresponding values in the given array. * * @param array $values An array of choice values. Not existing values in * this array are ignored * * @return array An array of indices with ascending, 0-based numeric keys * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values); } PK!В4 4 ,Extension/Core/ChoiceList/LazyChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A choice list that is loaded lazily * * This list loads itself as soon as any of the getters is accessed for the * first time. You should implement loadChoiceList() in your child classes, * which should return a ChoiceListInterface instance. * * @author Bernhard Schussek */ abstract class LazyChoiceList implements ChoiceListInterface { /** * The loaded choice list * * @var ChoiceListInterface */ private $choiceList; /** * {@inheritdoc} */ public function getChoices() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getChoices(); } /** * {@inheritdoc} */ public function getValues() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getValues(); } /** * {@inheritdoc} */ public function getPreferredViews() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getPreferredViews(); } /** * {@inheritdoc} */ public function getRemainingViews() { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getRemainingViews(); } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getChoicesForValues($values); } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getValuesForChoices($choices); } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getIndicesForChoices($choices); } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { if (!$this->choiceList) { $this->load(); } return $this->choiceList->getIndicesForValues($values); } /** * Loads the choice list * * Should be implemented by child classes. * * @return ChoiceListInterface The loaded choice list */ abstract protected function loadChoiceList(); private function load() { $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { throw new InvalidArgumentException(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList))); } $this->choiceList = $choiceList; } } PK!'ç??(Extension/Core/ChoiceList/ChoiceList.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Extension\Core\View\ChoiceView; /** * A choice list for choices of arbitrary data types. * * Choices and labels are passed in two arrays. The indices of the choices * and the labels should match. Choices may also be given as hierarchy of * unlimited depth by creating nested arrays. The title of the sub-hierarchy * can be stored in the array key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. * * * $choices = array(true, false); * $labels = array('Agree', 'Disagree'); * $choiceList = new ChoiceList($choices, $labels); * * * @author Bernhard Schussek */ class ChoiceList implements ChoiceListInterface { /** * The choices with their indices as keys. * * @var array */ private $choices = array(); /** * The choice values with the indices of the matching choices as keys. * * @var array */ private $values = array(); /** * The preferred view objects as hierarchy containing also the choice groups * with the indices of the matching choices as bottom-level keys. * * @var array */ private $preferredViews = array(); /** * The non-preferred view objects as hierarchy containing also the choice * groups with the indices of the matching choices as bottom-level keys. * * @var array */ private $remainingViews = array(); /** * Creates a new choice list. * * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth. Hierarchies are * created by creating nested arrays. The title of * the sub-hierarchy can be stored in the array * key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. * @param array $labels The array of labels. The structure of this array * should match the structure of $choices. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * * @throws UnexpectedTypeException If the choices are not an array or \Traversable. */ public function __construct($choices, array $labels, array $preferredChoices = array()) { if (!is_array($choices) && !$choices instanceof \Traversable) { throw new UnexpectedTypeException($choices, 'array or \Traversable'); } $this->initialize($choices, $labels, $preferredChoices); } /** * Initializes the list with choices. * * Safe to be called multiple times. The list is cleared on every call. * * @param array|\Traversable $choices The choices to write into the list. * @param array $labels The labels belonging to the choices. * @param array $preferredChoices The choices to display with priority. */ protected function initialize($choices, array $labels, array $preferredChoices) { $this->choices = array(); $this->values = array(); $this->preferredViews = array(); $this->remainingViews = array(); $this->addChoices( $this->preferredViews, $this->remainingViews, $choices, $labels, $preferredChoices ); } /** * {@inheritdoc} */ public function getChoices() { return $this->choices; } /** * {@inheritdoc} */ public function getValues() { return $this->values; } /** * {@inheritdoc} */ public function getPreferredViews() { return $this->preferredViews; } /** * {@inheritdoc} */ public function getRemainingViews() { return $this->remainingViews; } /** * {@inheritdoc} */ public function getChoicesForValues(array $values) { $values = $this->fixValues($values); $choices = array(); foreach ($values as $i => $givenValue) { foreach ($this->values as $j => $value) { if ($value === $givenValue) { $choices[$i] = $this->choices[$j]; unset($values[$i]); if (0 === count($values)) { break 2; } } } } return $choices; } /** * {@inheritdoc} */ public function getValuesForChoices(array $choices) { $choices = $this->fixChoices($choices); $values = array(); foreach ($choices as $i => $givenChoice) { foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { $values[$i] = $this->values[$j]; unset($choices[$i]); if (0 === count($choices)) { break 2; } } } } return $values; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { $choices = $this->fixChoices($choices); $indices = array(); foreach ($choices as $i => $givenChoice) { foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { $indices[$i] = $j; unset($choices[$i]); if (0 === count($choices)) { break 2; } } } } return $indices; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { $values = $this->fixValues($values); $indices = array(); foreach ($values as $i => $givenValue) { foreach ($this->values as $j => $value) { if ($value === $givenValue) { $indices[$i] = $j; unset($values[$i]); if (0 === count($values)) { break 2; } } } } return $indices; } /** * Recursively adds the given choices to the list. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array|\Traversable $choices The list of choices. * @param array $labels The labels corresponding to the choices. * @param array $preferredChoices The preferred choices. * * @throws InvalidArgumentException If the structures of the choices and labels array do not match. * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { // Add choices to the nested buckets foreach ($choices as $group => $choice) { if (!array_key_exists($group, $labels)) { throw new InvalidArgumentException('The structures of the choices and labels array do not match.'); } if (is_array($choice)) { // Don't do the work if the array is empty if (count($choice) > 0) { $this->addChoiceGroup( $group, $bucketForPreferred, $bucketForRemaining, $choice, $labels[$group], $preferredChoices ); } } else { $this->addChoice( $bucketForPreferred, $bucketForRemaining, $choice, $labels[$group], $preferredChoices ); } } } /** * Recursively adds a choice group. * * @param string $group The name of the group. * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param array $choices The list of choices in the group. * @param array $labels The labels corresponding to the choices in the group. * @param array $preferredChoices The preferred choices. * * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bucketForRemaining, array $choices, array $labels, array $preferredChoices) { // If this is a choice group, create a new level in the choice // key hierarchy $bucketForPreferred[$group] = array(); $bucketForRemaining[$group] = array(); $this->addChoices( $bucketForPreferred[$group], $bucketForRemaining[$group], $choices, $labels, $preferredChoices ); // Remove child levels if empty if (empty($bucketForPreferred[$group])) { unset($bucketForPreferred[$group]); } if (empty($bucketForRemaining[$group])) { unset($bucketForRemaining[$group]); } } /** * Adds a new choice. * * @param array $bucketForPreferred The bucket where to store the preferred * view objects. * @param array $bucketForRemaining The bucket where to store the * non-preferred view objects. * @param mixed $choice The choice to add. * @param string $label The label for the choice. * @param array $preferredChoices The preferred choices. * * @throws InvalidConfigurationException If no valid value or index could be created. */ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemaining, $choice, $label, array $preferredChoices) { $index = $this->createIndex($choice); if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) { throw new InvalidConfigurationException(sprintf('The index "%s" created by the choice list is invalid. It should be a valid, non-empty Form name.', $index)); } $value = $this->createValue($choice); if (!is_string($value)) { throw new InvalidConfigurationException(sprintf('The value created by the choice list is of type "%s", but should be a string.', gettype($value))); } $view = new ChoiceView($choice, $value, $label); $this->choices[$index] = $this->fixChoice($choice); $this->values[$index] = $value; if ($this->isPreferred($choice, $preferredChoices)) { $bucketForPreferred[$index] = $view; } else { $bucketForRemaining[$index] = $view; } } /** * Returns whether the given choice should be preferred judging by the * given array of preferred choices. * * Extension point to optimize performance by changing the structure of the * $preferredChoices array. * * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * * @return Boolean Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { return false !== array_search($choice, $preferredChoices, true); } /** * Creates a new unique index for this choice. * * Extension point to change the indexing strategy. * * @param mixed $choice The choice to create an index for * * @return integer|string A unique index containing only ASCII letters, * digits and underscores. */ protected function createIndex($choice) { return count($this->choices); } /** * Creates a new unique value for this choice. * * By default, an integer is generated since it cannot be guaranteed that * all values in the list are convertible to (unique) strings. Subclasses * can override this behaviour if they can guarantee this property. * * @param mixed $choice The choice to create a value for * * @return string A unique string. */ protected function createValue($choice) { return (string) count($this->values); } /** * Fixes the data type of the given choice value to avoid comparison * problems. * * @param mixed $value The choice value. * * @return string The value as string. */ protected function fixValue($value) { return (string) $value; } /** * Fixes the data types of the given choice values to avoid comparison * problems. * * @param array $values The choice values. * * @return array The values as strings. */ protected function fixValues(array $values) { foreach ($values as $i => $value) { $values[$i] = $this->fixValue($value); } return $values; } /** * Fixes the data type of the given choice index to avoid comparison * problems. * * @param mixed $index The choice index. * * @return integer|string The index as PHP array key. */ protected function fixIndex($index) { if (is_bool($index) || (string) (int) $index === (string) $index) { return (int) $index; } return (string) $index; } /** * Fixes the data types of the given choice indices to avoid comparison * problems. * * @param array $indices The choice indices. * * @return array The indices as strings. */ protected function fixIndices(array $indices) { foreach ($indices as $i => $index) { $indices[$i] = $this->fixIndex($index); } return $indices; } /** * Fixes the data type of the given choice to avoid comparison problems. * * Extension point. In this implementation, choices are guaranteed to * always maintain their type and thus can be typesafely compared. * * @param mixed $choice The choice * * @return mixed The fixed choice */ protected function fixChoice($choice) { return $choice; } /** * Fixes the data type of the given choices to avoid comparison problems. * * @param array $choices The choices. * * @return array The fixed choices. * * @see fixChoice */ protected function fixChoices(array $choices) { return $choices; } } PK!&PP"Extension/Core/View/ChoiceView.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\View; /** * Represents a choice in templates. * * @author Bernhard Schussek */ class ChoiceView { /** * The original choice value. * * @var mixed */ public $data; /** * The view representation of the choice. * * @var string */ public $value; /** * The label displayed to humans. * * @var string */ public $label; /** * Creates a new ChoiceView. * * @param mixed $data The original choice. * @param string $value The view representation of the choice. * @param string $label The label displayed to humans. */ public function __construct($data, $value, $label) { $this->data = $data; $this->value = $value; $this->label = $label; } } PK!  0Extension/Core/DataMapper/PropertyPathMapper.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataMapper; use Symfony\Component\Form\DataMapperInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A data mapper using property paths to read/write data. * * @author Bernhard Schussek */ class PropertyPathMapper implements DataMapperInterface { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * Creates a new property path mapper. * * @param PropertyAccessorInterface $propertyAccessor */ public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritdoc} */ public function mapDataToForms($data, $forms) { $empty = null === $data || array() === $data; if (!$empty && !is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); if (!$empty && null !== $propertyPath && $config->getMapped()) { $form->setData($this->propertyAccessor->getValue($data, $propertyPath)); } else { $form->setData($form->getConfig()->getData()); } } } /** * {@inheritdoc} */ public function mapFormsToData($forms, &$data) { if (null === $data) { return; } if (!is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); // Write-back is disabled if the form is not synchronized (transformation failed), // if the form was not submitted and if the form is disabled (modification not allowed) if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { // If the field is of type DateTime and the data is the same skip the update to // keep the original object hash if ($form->getData() instanceof \DateTime && $form->getData() == $this->propertyAccessor->getValue($data, $propertyPath)) { continue; } // If the data is identical to the value in $data, we are // dealing with a reference if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) { $this->propertyAccessor->setValue($data, $propertyPath, $form->getData()); } } } } } PK!O###EExtension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a number type and a localized number with grouping * (each thousand) and comma separators. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class NumberToLocalizedStringTransformer implements DataTransformerInterface { /** * Rounds a number towards positive infinity. * * Rounds 1.4 to 2 and -1.4 to -1. */ const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; /** * Rounds a number towards negative infinity. * * Rounds 1.4 to 1 and -1.4 to -2. */ const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; /** * Rounds a number away from zero. * * Rounds 1.4 to 2 and -1.4 to -2. */ const ROUND_UP = \NumberFormatter::ROUND_UP; /** * Rounds a number towards zero. * * Rounds 1.4 to 1 and -1.4 to -1. */ const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; /** * Rounds to the nearest number and halves to the next even number. * * Rounds 2.5, 1.6 and 1.5 to 2 and 1.4 to 1. */ const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN; /** * Rounds to the nearest number and halves away from zero. * * Rounds 2.5 to 3, 1.6 and 1.5 to 2 and 1.4 to 1. */ const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP; /** * Rounds to the nearest number and halves towards zero. * * Rounds 2.5 and 1.6 to 2, 1.5 and 1.4 to 1. */ const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN; /** * Alias for {@link self::ROUND_HALF_EVEN}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFEVEN = self::ROUND_HALF_EVEN; /** * Alias for {@link self::ROUND_HALF_UP}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFUP = self::ROUND_HALF_UP; /** * Alias for {@link self::ROUND_HALF_DOWN}. * * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. */ const ROUND_HALFDOWN = self::ROUND_HALF_DOWN; protected $precision; protected $grouping; protected $roundingMode; public function __construct($precision = null, $grouping = false, $roundingMode = self::ROUND_HALF_UP) { if (null === $grouping) { $grouping = false; } if (null === $roundingMode) { $roundingMode = self::ROUND_HALF_UP; } $this->precision = $precision; $this->grouping = $grouping; $this->roundingMode = $roundingMode; } /** * Transforms a number type into localized number. * * @param integer|float $value Number value. * * @return string Localized value. * * @throws TransformationFailedException If the given value is not numeric * or if the value can not be transformed. */ public function transform($value) { if (null === $value) { return ''; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } $formatter = $this->getNumberFormatter(); $value = $formatter->format($value); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } // Convert fixed spaces to normal ones $value = str_replace("\xc2\xa0", ' ', $value); return $value; } /** * Transforms a localized number into an integer or float * * @param string $value The localized value * * @return integer|float The numeric value * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } if ('NaN' === $value) { throw new TransformationFailedException('"NaN" is not a valid number'); } $position = 0; $formatter = $this->getNumberFormatter(); $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); if ('.' !== $decSep && (!$this->grouping || '.' !== $groupSep)) { $value = str_replace('.', $decSep, $value); } if (',' !== $decSep && (!$this->grouping || ',' !== $groupSep)) { $value = str_replace(',', $decSep, $value); } $result = $formatter->parse($value, \NumberFormatter::TYPE_DOUBLE, $position); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if ($result >= PHP_INT_MAX || $result <= -PHP_INT_MAX) { throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) { $strlen = function ($string) use ($encoding) { return mb_strlen($string, $encoding); }; $substr = function ($string, $offset, $length) use ($encoding) { return mb_substr($string, $offset, $length, $encoding); }; } else { $strlen = 'strlen'; $substr = 'substr'; } $length = $strlen($value); // After parsing, position holds the index of the character where the // parsing stopped if ($position < $length) { // Check if there are unrecognized characters at the end of the // number (excluding whitespace characters) $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0"); if ('' !== $remainder) { throw new TransformationFailedException( sprintf('The number contains unrecognized characters: "%s"', $remainder) ); } } // NumberFormatter::parse() does not round return $this->round($result); } /** * Returns a preconfigured \NumberFormatter instance * * @return \NumberFormatter */ protected function getNumberFormatter() { $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); if (null !== $this->precision) { $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision); $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode); } $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping); return $formatter; } /** * Rounds a number according to the configured precision and rounding mode. * * @param integer|float $number A number. * * @return integer|float The rounded number. */ private function round($number) { if (null !== $this->precision && null !== $this->roundingMode) { // shift number to maintain the correct precision during rounding $roundingCoef = pow(10, $this->precision); $number *= $roundingCoef; switch ($this->roundingMode) { case self::ROUND_CEILING: $number = ceil($number); break; case self::ROUND_FLOOR: $number = floor($number); break; case self::ROUND_UP: $number = $number > 0 ? ceil($number) : floor($number); break; case self::ROUND_DOWN: $number = $number > 0 ? floor($number) : ceil($number); break; case self::ROUND_HALF_EVEN: $number = round($number, 0, PHP_ROUND_HALF_EVEN); break; case self::ROUND_HALF_UP: $number = round($number, 0, PHP_ROUND_HALF_UP); break; case self::ROUND_HALF_DOWN: $number = round($number, 0, PHP_ROUND_HALF_DOWN); break; } $number /= $roundingCoef; } return $number; } } PK!)b""GExtension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized time and a localized time string * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer { private $dateFormat; private $timeFormat; private $pattern; private $calendar; /** * Constructor. * * @see BaseDateTimeTransformer::formats for available format options * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param integer $dateFormat The date format * @param integer $timeFormat The time format * @param integer $calendar One of the \IntlDateFormatter calendar constants * @param string $pattern A pattern to pass to \IntlDateFormatter * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null) { parent::__construct($inputTimezone, $outputTimezone); if (null === $dateFormat) { $dateFormat = \IntlDateFormatter::MEDIUM; } if (null === $timeFormat) { $timeFormat = \IntlDateFormatter::SHORT; } if (!in_array($dateFormat, self::$formats, true)) { throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats)); } if (!in_array($timeFormat, self::$formats, true)) { throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats)); } $this->dateFormat = $dateFormat; $this->timeFormat = $timeFormat; $this->calendar = $calendar; $this->pattern = $pattern; } /** * Transforms a normalized date into a localized date string/array. * * @param \DateTime $dateTime Normalized date. * * @return string|array Localized date string/array. * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the date could not * be transformed. */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } // convert time to UTC before passing it to the formatter $dateTime = clone $dateTime; if ('UTC' !== $this->inputTimezone) { $dateTime->setTimezone(new \DateTimeZone('UTC')); } $value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U')); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); } return $value; } /** * Transforms a localized date string/array into a normalized date. * * @param string|array $value Localized date string/array * * @return \DateTime Normalized date * * @throws TransformationFailedException if the given value is not a string, * if the date could not be parsed or * if the input timezone is not supported */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } $timestamp = $this->getIntlDateFormatter()->parse($value); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); } try { // read timestamp into DateTime object - the formatter delivers in UTC $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ('UTC' !== $this->inputTimezone) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } return $dateTime; } /** * Returns a preconfigured IntlDateFormatter instance * * @return \IntlDateFormatter */ protected function getIntlDateFormatter() { $dateFormat = $this->dateFormat; $timeFormat = $this->timeFormat; $timezone = $this->outputTimezone; $calendar = $this->calendar; $pattern = $this->pattern; $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern); $intlDateFormatter->setLenient(false); return $intlDateFormatter; } } PK!e^  ?Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer { /** * {@inheritDoc} */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime = clone $dateTime; $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c')); } /** * {@inheritDoc} */ public function reverseTransform($rfc3339) { if (!is_string($rfc3339)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $rfc3339) { return null; } try { $dateTime = new \DateTime($rfc3339); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ($this->outputTimezone !== $dateTime->getTimezone()->getName()) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) { if (!checkdate($matches[2], $matches[3], $matches[1])) { throw new TransformationFailedException(sprintf( 'The date "%s-%s-%s" is not a valid date.', $matches[1], $matches[2], $matches[3] )); } } return $dateTime; } } PK!Þ AExtension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a timestamp and a DateTime object * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer { /** * Transforms a DateTime object into a timestamp in the configured timezone. * * @param \DateTime $value A \DateTime object * * @return integer A timestamp * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the output * timezone is not supported. */ public function transform($value) { if (null === $value) { return null; } if (!$value instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $value = clone $value; try { $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return (int) $value->format('U'); } /** * Transforms a timestamp in the configured timezone into a DateTime object * * @param string $value A timestamp * * @return \DateTime A \DateTime object * * @throws TransformationFailedException If the given value is not a timestamp * or if the given timestamp is invalid. */ public function reverseTransform($value) { if (null === $value) { return null; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } try { $dateTime = new \DateTime(); $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); $dateTime->setTimestamp($value); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK!c8V 7Extension/Core/DataTransformer/DataTransformerChain.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Passes a value through multiple value transformers * * @author Bernhard Schussek */ class DataTransformerChain implements DataTransformerInterface { /** * The value transformers * @var DataTransformerInterface[] */ protected $transformers; /** * Uses the given value transformers to transform values * * @param array $transformers */ public function __construct(array $transformers) { $this->transformers = $transformers; } /** * Passes the value through the transform() method of all nested transformers * * The transformers receive the value in the same order as they were passed * to the constructor. Each transformer receives the result of the previous * transformer as input. The output of the last transformer is returned * by this method. * * @param mixed $value The original value * * @return mixed The transformed value * * @throws TransformationFailedException */ public function transform($value) { foreach ($this->transformers as $transformer) { $value = $transformer->transform($value); } return $value; } /** * Passes the value through the reverseTransform() method of all nested * transformers * * The transformers receive the value in the reverse order as they were passed * to the constructor. Each transformer receives the result of the previous * transformer as input. The output of the last transformer is returned * by this method. * * @param mixed $value The transformed value * * @return mixed The reverse-transformed value * * @throws TransformationFailedException */ public function reverseTransform($value) { for ($i = count($this->transformers) - 1; $i >= 0; --$i) { $value = $this->transformers[$i]->reverseTransform($value); } return $value; } } PK!;ddFExtension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized format (integer or float) and a percentage value. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class PercentToLocalizedStringTransformer implements DataTransformerInterface { const FRACTIONAL = 'fractional'; const INTEGER = 'integer'; protected static $types = array( self::FRACTIONAL, self::INTEGER, ); private $type; private $precision; /** * Constructor. * * @see self::$types for a list of supported types * * @param integer $precision The precision * @param string $type One of the supported types * * @throws UnexpectedTypeException if the given value of type is unknown */ public function __construct($precision = null, $type = null) { if (null === $precision) { $precision = 0; } if (null === $type) { $type = self::FRACTIONAL; } if (!in_array($type, self::$types, true)) { throw new UnexpectedTypeException($type, implode('", "', self::$types)); } $this->type = $type; $this->precision = $precision; } /** * Transforms between a normalized format (integer or float) into a percentage value. * * @param number $value Normalized value * * @return number Percentage value * * @throws TransformationFailedException If the given value is not numeric or * if the value could not be transformed. */ public function transform($value) { if (null === $value) { return ''; } if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } if (self::FRACTIONAL == $this->type) { $value *= 100; } $formatter = $this->getNumberFormatter(); $value = $formatter->format($value); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } // replace the UTF-8 non break spaces return $value; } /** * Transforms between a percentage value into a normalized format (integer or float). * * @param number $value Percentage value. * * @return number Normalized value. * * @throws TransformationFailedException If the given value is not a string or * if the value could not be transformed. */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return null; } $formatter = $this->getNumberFormatter(); // replace normal spaces so that the formatter can read them $value = $formatter->parse(str_replace(' ', ' ', $value)); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if (self::FRACTIONAL == $this->type) { $value /= 100; } return $value; } /** * Returns a preconfigured \NumberFormatter instance * * @return \NumberFormatter */ protected function getNumberFormatter() { $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision); return $formatter; } } PK!Ze  =Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a normalized time and a localized time string/array. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToArrayTransformer extends BaseDateTimeTransformer { private $pad; private $fields; /** * Constructor. * * @param string $inputTimezone The input timezone * @param string $outputTimezone The output timezone * @param array $fields The date fields * @param Boolean $pad Whether to use padding * * @throws UnexpectedTypeException if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false) { parent::__construct($inputTimezone, $outputTimezone); if (null === $fields) { $fields = array('year', 'month', 'day', 'hour', 'minute', 'second'); } $this->fields = $fields; $this->pad = (Boolean) $pad; } /** * Transforms a normalized date into a localized date. * * @param \DateTime $dateTime Normalized date. * * @return array Localized date. * * @throws TransformationFailedException If the given value is not an * instance of \DateTime or if the * output timezone is not supported. */ public function transform($dateTime) { if (null === $dateTime) { return array_intersect_key(array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ), array_flip($this->fields)); } if (!$dateTime instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $dateTime = clone $dateTime; if ($this->inputTimezone !== $this->outputTimezone) { try { $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } } $result = array_intersect_key(array( 'year' => $dateTime->format('Y'), 'month' => $dateTime->format('m'), 'day' => $dateTime->format('d'), 'hour' => $dateTime->format('H'), 'minute' => $dateTime->format('i'), 'second' => $dateTime->format('s'), ), array_flip($this->fields)); if (!$this->pad) { foreach ($result as &$entry) { // remove leading zeros $entry = (string) (int) $entry; } } return $result; } /** * Transforms a localized date into a normalized date. * * @param array $value Localized date * * @return \DateTime Normalized date * * @throws TransformationFailedException If the given value is not an array, * if the value could not be transformed * or if the input timezone is not * supported. */ public function reverseTransform($value) { if (null === $value) { return null; } if (!is_array($value)) { throw new TransformationFailedException('Expected an array.'); } if ('' === implode('', $value)) { return null; } $emptyFields = array(); foreach ($this->fields as $field) { if (!isset($value[$field])) { $emptyFields[] = $field; } } if (count($emptyFields) > 0) { throw new TransformationFailedException( sprintf('The fields "%s" should not be empty', implode('", "', $emptyFields) )); } if (isset($value['month']) && !ctype_digit((string) $value['month'])) { throw new TransformationFailedException('This month is invalid'); } if (isset($value['day']) && !ctype_digit((string) $value['day'])) { throw new TransformationFailedException('This day is invalid'); } if (isset($value['year']) && !ctype_digit((string) $value['year'])) { throw new TransformationFailedException('This year is invalid'); } if (!empty($value['month']) && !empty($value['day']) && !empty($value['year']) && false === checkdate($value['month'], $value['day'], $value['year'])) { throw new TransformationFailedException('This is an invalid date'); } if (isset($value['hour']) && !ctype_digit((string) $value['hour'])) { throw new TransformationFailedException('This hour is invalid'); } if (isset($value['minute']) && !ctype_digit((string) $value['minute'])) { throw new TransformationFailedException('This minute is invalid'); } if (isset($value['second']) && !ctype_digit((string) $value['second'])) { throw new TransformationFailedException('This second is invalid'); } try { $dateTime = new \DateTime(sprintf( '%s-%s-%s %s:%s:%s %s', empty($value['year']) ? '1970' : $value['year'], empty($value['month']) ? '1' : $value['month'], empty($value['day']) ? '1' : $value['day'], empty($value['hour']) ? '0' : $value['hour'], empty($value['minute']) ? '0' : $value['minute'], empty($value['second']) ? '0' : $value['second'], $this->outputTimezone )); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK!Lpx&&BExtension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ChoiceToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; private $placeholderPresent; /** * Constructor. * * @param ChoiceListInterface $choiceList * @param Boolean $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; $this->placeholderPresent = $placeholderPresent; } /** * Transforms a single choice to a format appropriate for the nested * checkboxes/radio buttons. * * The result is an array with the options as keys and true/false as values, * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * * @param mixed $choice An array if "multiple" is set to true, a scalar * value otherwise. * * @return mixed An array * * @throws TransformationFailedException If the given value is not scalar or * if the choices can not be retrieved. */ public function transform($choice) { try { $values = $this->choiceList->getValues(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); foreach ($values as $i => $value) { $values[$i] = isset($valueMap[$value]); } if ($this->placeholderPresent) { $values['placeholder'] = 0 === count($valueMap); } return $values; } /** * Transforms a checkbox/radio button array to a single choice. * * The input value is an array with the choices as keys and true/false as * values, depending on whether a given choice is selected. The output * is the selected choice. * * @param array $values An array of values * * @return mixed A scalar value * * @throws TransformationFailedException If the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be * found. */ public function reverseTransform($values) { if (!is_array($values)) { throw new TransformationFailedException('Expected an array.'); } try { $choices = $this->choiceList->getChoices(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; } elseif ($this->placeholderPresent && 'placeholder' === $i) { return null; } else { throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i)); } } } return null; } } PK!  ?Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ValueToDuplicatesTransformer implements DataTransformerInterface { private $keys; public function __construct(array $keys) { $this->keys = $keys; } /** * Duplicates the given value through the array. * * @param mixed $value The value * * @return array The array */ public function transform($value) { $result = array(); foreach ($this->keys as $key) { $result[$key] = $value; } return $result; } /** * Extracts the duplicated value from an array. * * @param array $array * * @return mixed The value * * @throws TransformationFailedException If the given value is not an array or * if the given array can not be transformed. */ public function reverseTransform($array) { if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } $result = current($array); $emptyKeys = array(); foreach ($this->keys as $key) { if (!empty($array[$key])) { if ($array[$key] !== $result) { throw new TransformationFailedException( 'All values in the array should be the same' ); } } else { $emptyKeys[] = $key; } } if (count($emptyKeys) > 0) { if (count($emptyKeys) == count($this->keys)) { // All keys empty return null; } throw new TransformationFailedException( sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys) )); } return $result; } } PK!'tqk55CExtension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ChoicesToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } /** * Transforms an array of choices to a format appropriate for the nested * checkboxes/radio buttons. * * The result is an array with the options as keys and true/false as values, * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * * @param mixed $array An array * * @return mixed An array * * @throws TransformationFailedException If the given value is not an array * or if the choices can not be retrieved. */ public function transform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } try { $values = $this->choiceList->getValues(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $valueMap = array_flip($this->choiceList->getValuesForChoices($array)); foreach ($values as $i => $value) { $values[$i] = isset($valueMap[$value]); } return $values; } /** * Transforms a checkbox/radio button array to an array of choices. * * The input value is an array with the choices as keys and true/false as * values, depending on whether a given choice is selected. The output * is an array with the selected choices. * * @param mixed $values An array * * @return mixed An array * * @throws TransformationFailedException If the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be * found. */ public function reverseTransform($values) { if (!is_array($values)) { throw new TransformationFailedException('Expected an array.'); } try { $choices = $this->choiceList->getChoices(); } catch (\Exception $e) { throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } $result = array(); $unknown = array(); foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { $result[] = $choices[$i]; } else { $unknown[] = $i; } } } if (count($unknown) > 0) { throw new TransformationFailedException(sprintf('The choices "%s" were not found', implode('", "', $unknown))); } return $result; } } PK!gg=Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * @author Bernhard Schussek */ class ChoicesToValuesTransformer implements DataTransformerInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } /** * @param array $array * * @return array * * @throws TransformationFailedException If the given value is not an array. */ public function transform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } return $this->choiceList->getValuesForChoices($array); } /** * @param array $array * * @return array * * @throws TransformationFailedException If the given value is not an array * or if no matching choice could be * found for some given value. */ public function reverseTransform($array) { if (null === $array) { return array(); } if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } $choices = $this->choiceList->getChoicesForValues($array); if (count($choices) !== count($array)) { throw new TransformationFailedException('Could not find all matching choices for the given values'); } return $choices; } } PK!UdqFExtension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; /** * Transforms between an integer and a localized number with grouping * (each thousand) and comma separators. * * @author Bernhard Schussek */ class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { /** * Constructs a transformer. * * @param integer $precision Unused. * @param Boolean $grouping Whether thousands should be grouped. * @param integer $roundingMode One of the ROUND_ constants in this class. */ public function __construct($precision = 0, $grouping = false, $roundingMode = self::ROUND_DOWN) { if (null === $roundingMode) { $roundingMode = self::ROUND_DOWN; } parent::__construct(0, $grouping, $roundingMode); } /** * {@inheritDoc} */ public function reverseTransform($value) { $result = parent::reverseTransform($value); return null !== $result ? (int) $result : null; } } PK!ΎgW >Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Transforms between a date string and a DateTime object * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToStringTransformer extends BaseDateTimeTransformer { /** * Format used for generating strings * @var string */ private $generateFormat; /** * Format used for parsing strings * * Different than the {@link $generateFormat} because formats for parsing * support additional characters in PHP that are not supported for * generating strings. * * @var string */ private $parseFormat; /** * Whether to parse by appending a pipe "|" to the parse format. * * This only works as of PHP 5.3.7. * * @var Boolean */ private $parseUsingPipe; /** * Transforms a \DateTime instance to a string * * @see \DateTime::format() for supported formats * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param string $format The date format * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format * * @throws UnexpectedTypeException if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = null) { parent::__construct($inputTimezone, $outputTimezone); $this->generateFormat = $this->parseFormat = $format; // The pipe in the parser pattern only works as of PHP 5.3.7 // See http://bugs.php.net/54316 $this->parseUsingPipe = null === $parseUsingPipe ? version_compare(phpversion(), '5.3.7', '>=') : $parseUsingPipe; // See http://php.net/manual/en/datetime.createfromformat.php // The character "|" in the format makes sure that the parts of a date // that are *not* specified in the format are reset to the corresponding // values from 1970-01-01 00:00:00 instead of the current time. // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47", // where the time corresponds to the current server time. // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00", // which is at least deterministic and thus used here. if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) { $this->parseFormat .= '|'; } } /** * Transforms a DateTime object into a date string with the configured format * and timezone * * @param \DateTime $value A DateTime object * * @return string A value as produced by PHP's date() function * * @throws TransformationFailedException If the given value is not a \DateTime * instance or if the output timezone * is not supported. */ public function transform($value) { if (null === $value) { return ''; } if (!$value instanceof \DateTime) { throw new TransformationFailedException('Expected a \DateTime.'); } $value = clone $value; try { $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $value->format($this->generateFormat); } /** * Transforms a date string in the configured timezone into a DateTime object. * * @param string $value A value as produced by PHP's date() function * * @return \DateTime An instance of \DateTime * * @throws TransformationFailedException If the given value is not a string, * if the date could not be parsed or * if the input timezone is not supported. */ public function reverseTransform($value) { if (empty($value)) { return null; } if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } try { $outputTz = new \DateTimeZone($this->outputTimezone); $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz); $lastErrors = \DateTime::getLastErrors(); if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) { throw new TransformationFailedException( implode(', ', array_merge( array_values($lastErrors['warnings']), array_values($lastErrors['errors']) )) ); } // On PHP versions < 5.3.7 we need to emulate the pipe operator // and reset parts not given in the format to their equivalent // of the UNIX base timestamp. if (!$this->parseUsingPipe) { list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s')); // Check which of the date parts are present in the pattern preg_match( '/(' . '(?P[djDl])|' . '(?P[FMmn])|' . '(?P[Yy])|' . '(?P[ghGH])|' . '(?Pi)|' . '(?Ps)|' . '(?Pz)|' . '(?PU)|' . '[^djDlFMmnYyghGHiszU]' . ')*/', $this->parseFormat, $matches ); // preg_match() does not guarantee to set all indices, so // set them unless given $matches = array_merge(array( 'day' => false, 'month' => false, 'year' => false, 'hour' => false, 'minute' => false, 'second' => false, 'dayofyear' => false, 'timestamp' => false, ), $matches); // Reset all parts that don't exist in the format to the // corresponding part of the UNIX base timestamp if (!$matches['timestamp']) { if (!$matches['dayofyear']) { if (!$matches['day']) { $day = 1; } if (!$matches['month']) { $month = 1; } } if (!$matches['year']) { $year = 1970; } if (!$matches['hour']) { $hour = 0; } if (!$matches['minute']) { $minute = 0; } if (!$matches['second']) { $second = 0; } $dateTime->setDate($year, $month, $day); $dateTime->setTime($hour, $minute, $second); } } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone)); } } catch (TransformationFailedException $e) { throw $e; } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } return $dateTime; } } PK!"h;Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; /** * @author Bernhard Schussek */ class ChoiceToValueTransformer implements DataTransformerInterface { private $choiceList; /** * Constructor. * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) { $this->choiceList = $choiceList; } public function transform($choice) { return (string) current($this->choiceList->getValuesForChoices(array($choice))); } public function reverseTransform($value) { if (null !== $value && !is_scalar($value)) { throw new TransformationFailedException('Expected a scalar.'); } // These are now valid ChoiceList values, so we can return null // right away if ('' === $value || null === $value) { return null; } $choices = $this->choiceList->getChoicesForValues(array($value)); if (1 !== count($choices)) { throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique', $value)); } $choice = current($choices); return '' === $choice ? null : $choice; } } PK!H  :Extension/Core/DataTransformer/ArrayToPartsTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * @author Bernhard Schussek */ class ArrayToPartsTransformer implements DataTransformerInterface { private $partMapping; public function __construct(array $partMapping) { $this->partMapping = $partMapping; } public function transform($array) { if (null === $array) { $array = array(); } if (!is_array($array) ) { throw new TransformationFailedException('Expected an array.'); } $result = array(); foreach ($this->partMapping as $partKey => $originalKeys) { if (empty($array)) { $result[$partKey] = null; } else { $result[$partKey] = array_intersect_key($array, array_flip($originalKeys)); } } return $result; } public function reverseTransform($array) { if (!is_array($array) ) { throw new TransformationFailedException('Expected an array.'); } $result = array(); $emptyKeys = array(); foreach ($this->partMapping as $partKey => $originalKeys) { if (!empty($array[$partKey])) { foreach ($originalKeys as $originalKey) { if (isset($array[$partKey][$originalKey])) { $result[$originalKey] = $array[$partKey][$originalKey]; } } } else { $emptyKeys[] = $partKey; } } if (count($emptyKeys) > 0) { if (count($emptyKeys) === count($this->partMapping)) { // All parts empty return null; } throw new TransformationFailedException( sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys) )); } return $result; } } PK!/C:Extension/Core/DataTransformer/BaseDateTimeTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; abstract class BaseDateTimeTransformer implements DataTransformerInterface { protected static $formats = array( \IntlDateFormatter::NONE, \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); protected $inputTimezone; protected $outputTimezone; /** * Constructor. * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * * @throws UnexpectedTypeException if a timezone is not a string * @throws InvalidArgumentException if a timezone is not valid */ public function __construct($inputTimezone = null, $outputTimezone = null) { if (!is_string($inputTimezone) && null !== $inputTimezone) { throw new UnexpectedTypeException($inputTimezone, 'string'); } if (!is_string($outputTimezone) && null !== $outputTimezone) { throw new UnexpectedTypeException($outputTimezone, 'string'); } $this->inputTimezone = $inputTimezone ?: date_default_timezone_get(); $this->outputTimezone = $outputTimezone ?: date_default_timezone_get(); // Check if input and output timezones are valid try { new \DateTimeZone($this->inputTimezone); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Input timezone is invalid: %s.', $this->inputTimezone), $e->getCode(), $e); } try { new \DateTimeZone($this->outputTimezone); } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Output timezone is invalid: %s.', $this->outputTimezone), $e->getCode(), $e); } } } PK!T=Extension/Core/DataTransformer/BooleanToStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a Boolean and a string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class BooleanToStringTransformer implements DataTransformerInterface { /** * The value emitted upon transform if the input is true * @var string */ private $trueValue; /** * Sets the value emitted upon transform if the input is true. * * @param string $trueValue */ public function __construct($trueValue) { $this->trueValue = $trueValue; } /** * Transforms a Boolean into a string. * * @param Boolean $value Boolean value. * * @return string String value. * * @throws TransformationFailedException If the given value is not a Boolean. */ public function transform($value) { if (null === $value) { return null; } if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } return $value ? $this->trueValue : null; } /** * Transforms a string into a Boolean. * * @param string $value String value. * * @return Boolean Boolean value. * * @throws TransformationFailedException If the given value is not a string. */ public function reverseTransform($value) { if (null === $value) { return false; } if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } return true; } } PK!]yD D DExtension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; /** * Transforms between a normalized format and a localized money string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { private $divisor; public function __construct($precision = 2, $grouping = true, $roundingMode = self::ROUND_HALF_UP, $divisor = 1) { if (null === $grouping) { $grouping = true; } if (null === $precision) { $precision = 2; } parent::__construct($precision, $grouping, $roundingMode); if (null === $divisor) { $divisor = 1; } $this->divisor = $divisor; } /** * Transforms a normalized format into a localized money string. * * @param number $value Normalized number * * @return string Localized money string. * * @throws TransformationFailedException If the given value is not numeric or * if the value can not be transformed. */ public function transform($value) { if (null !== $value) { if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } $value /= $this->divisor; } return parent::transform($value); } /** * Transforms a localized money string into a normalized format. * * @param string $value Localized money string * * @return number Normalized number * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. */ public function reverseTransform($value) { $value = parent::reverseTransform($value); if (null !== $value) { $value *= $this->divisor; } return $value; } } PK!/++"Extension/Core/Type/ChoiceType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToBooleanArrayTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class ChoiceType extends AbstractType { /** * Caches created choice lists. * @var array */ private $choiceListCache = array(); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) { throw new LogicException('Either the option "choices" or "choice_list" must be set.'); } if ($options['expanded']) { // Initialize all choices before doing the index check below. // This helps in cases where index checks are optimized for non // initialized choice lists. For example, when using an SQL driver, // the index check would read in one SQL query and the initialization // requires another SQL query. When the initialization is done first, // one SQL query is sufficient. $preferredViews = $options['choice_list']->getPreferredViews(); $remainingViews = $options['choice_list']->getRemainingViews(); // Check if the choices already contain the empty value // Only add the empty value option if this is not the case if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $placeholderView = new ChoiceView(null, '', $options['empty_value']); // "placeholder" is a reserved index // see also ChoiceListInterface::getIndicesForChoices() $this->addSubForms($builder, array('placeholder' => $placeholderView), $options); } $this->addSubForms($builder, $preferredViews, $options); $this->addSubForms($builder, $remainingViews, $options); if ($options['multiple']) { $builder->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list'])); $builder->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10); } else { $builder->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'], $builder->has('placeholder'))); $builder->addEventSubscriber(new FixRadioInputListener($options['choice_list'], $builder->has('placeholder')), 10); } } else { if ($options['multiple']) { $builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list'])); } else { $builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list'])); } } if ($options['multiple'] && $options['by_reference']) { // Make sure the collection created during the client->norm // transformation is merged back into the original collection $builder->addEventSubscriber(new MergeCollectionListener(true, true)); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'multiple' => $options['multiple'], 'expanded' => $options['expanded'], 'preferred_choices' => $options['choice_list']->getPreferredViews(), 'choices' => $options['choice_list']->getRemainingViews(), 'separator' => '-------------------', 'empty_value' => null, )); // The decision, whether a choice is selected, is potentially done // thousand of times during the rendering of a template. Provide a // closure here that is optimized for the value of the form, to // avoid making the type check inside the closure. if ($options['multiple']) { $view->vars['is_selected'] = function ($choice, array $values) { return false !== array_search($choice, $values, true); }; } else { $view->vars['is_selected'] = function ($choice, $value) { return $choice === $value; }; } // Check if the choices already contain the empty value $view->vars['empty_value_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array(''))); // Only add the empty value option if this is not the case if (null !== $options['empty_value'] && !$view->vars['empty_value_in_choices']) { $view->vars['empty_value'] = $options['empty_value']; } if ($options['multiple'] && !$options['expanded']) { // Add "[]" to the name in case a select tag with multiple options is // displayed. Otherwise only one of the selected options is sent in the // POST request. $view->vars['full_name'] = $view->vars['full_name'].'[]'; } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['expanded']) { // Radio buttons should have the same name as the parent $childName = $view->vars['full_name']; // Checkboxes should append "[]" to allow multiple selection if ($options['multiple']) { $childName .= '[]'; } foreach ($view as $childView) { $childView->vars['full_name'] = $childName; } } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $choiceListCache =& $this->choiceListCache; $choiceList = function (Options $options) use (&$choiceListCache) { // Harden against NULL values (like in EntityType and ModelType) $choices = null !== $options['choices'] ? $options['choices'] : array(); // Reuse existing choice lists in order to increase performance $hash = hash('sha256', json_encode(array($choices, $options['preferred_choices']))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']); } return $choiceListCache[$hash]; }; $emptyData = function (Options $options) { if ($options['multiple'] || $options['expanded']) { return array(); } return ''; }; $emptyValue = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) { if ($options['multiple']) { // never use an empty value for this case return null; } elseif (false === $emptyValue) { // an empty value should be added but the user decided otherwise return null; } elseif ($options['expanded'] && '' === $emptyValue) { // never use an empty label for radio buttons return 'None'; } // empty value has been set explicitly return $emptyValue; }; $compound = function (Options $options) { return $options['expanded']; }; $resolver->setDefaults(array( 'multiple' => false, 'expanded' => false, 'choice_list' => $choiceList, 'choices' => array(), 'preferred_choices' => array(), 'empty_data' => $emptyData, 'empty_value' => $emptyValue, 'error_bubbling' => false, 'compound' => $compound, // The view data is always a string, even if the "data" option // is manually set to an object. // See https://github.com/symfony/symfony/pull/5582 'data_class' => null, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedTypes(array( 'choice_list' => array('null', 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface'), )); } /** * {@inheritdoc} */ public function getName() { return 'choice'; } /** * Adds the sub fields for an expanded choice field. * * @param FormBuilderInterface $builder The form builder. * @param array $choiceViews The choice view objects. * @param array $options The build options. */ private function addSubForms(FormBuilderInterface $builder, array $choiceViews, array $options) { foreach ($choiceViews as $i => $choiceView) { if (is_array($choiceView)) { // Flatten groups $this->addSubForms($builder, $choiceView, $options); } else { $choiceOpts = array( 'value' => $choiceView->value, 'label' => $choiceView->label, 'translation_domain' => $options['translation_domain'], ); if ($options['multiple']) { $choiceType = 'checkbox'; // The user can check 0 or more checkboxes. If required // is true, he is required to check all of them. $choiceOpts['required'] = false; } else { $choiceType = 'radio'; } $builder->add($i, $choiceType, $choiceOpts); } } } } PK!h"Extension/Core/Type/ButtonType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\ButtonTypeInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * A form button. * * @author Bernhard Schussek */ class ButtonType extends BaseType implements ButtonTypeInterface { /** * {@inheritdoc} */ public function getParent() { return null; } /** * {@inheritdoc} */ public function getName() { return 'button'; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); $resolver->setDefaults(array( 'auto_initialize' => false, )); } } PK!DU"Extension/Core/Type/SubmitType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\SubmitButtonTypeInterface; /** * A submit button. * * @author Bernhard Schussek */ class SubmitType extends AbstractType implements SubmitButtonTypeInterface { public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['clicked'] = $form->isClicked(); } /** * {@inheritdoc} */ public function getParent() { return 'button'; } /** * {@inheritdoc} */ public function getName() { return 'submit'; } } PK!񍢸$Extension/Core/Type/CurrencyType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CurrencyType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getCurrencyBundle()->getCurrencyNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'currency'; } } PK!Ѝ'"Extension/Core/Type/HiddenType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class HiddenType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // hidden fields cannot have a required attribute 'required' => false, // Pass errors to the parent 'error_bubbling' => true, 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'hidden'; } } PK!D"Extension/Core/Type/LocaleType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LocaleType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getLocaleBundle()->getLocaleNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'locale'; } } PK!uƵ``#Extension/Core/Type/IntegerType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class IntegerType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer( new IntegerToLocalizedStringTransformer( $options['precision'], $options['grouping'], $options['rounding_mode'] )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, // Integer cast rounds towards 0, so do the same when displaying fractions 'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( IntegerToLocalizedStringTransformer::ROUND_FLOOR, IntegerToLocalizedStringTransformer::ROUND_DOWN, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN, IntegerToLocalizedStringTransformer::ROUND_HALF_UP, IntegerToLocalizedStringTransformer::ROUND_UP, IntegerToLocalizedStringTransformer::ROUND_CEILING, ), )); } /** * {@inheritdoc} */ public function getName() { return 'integer'; } } PK!a!Extension/Core/Type/ResetType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\ButtonTypeInterface; /** * A reset button. * * @author Bernhard Schussek */ class ResetType extends AbstractType implements ButtonTypeInterface { /** * {@inheritdoc} */ public function getParent() { return 'button'; } /** * {@inheritdoc} */ public function getName() { return 'reset'; } } PK!옇$Extension/Core/Type/PasswordType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PasswordType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { if ($options['always_empty'] || !$form->isSubmitted()) { $view->vars['value'] = ''; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'always_empty' => true, 'trim' => false, )); } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'password'; } } PK!ٝGG Extension/Core/Type/BaseType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * Encapsulates common logic of {@link FormType} and {@link ButtonType}. * * This type does not appear in the form's type inheritance chain and as such * cannot be extended (via {@link FormTypeExtension}s) nor themed. * * @author Bernhard Schussek */ abstract class BaseType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setDisabled($options['disabled']); $builder->setAutoInitialize($options['auto_initialize']); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $name = $form->getName(); $blockName = $options['block_name'] ?: $form->getName(); $translationDomain = $options['translation_domain']; if ($view->parent) { if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { $id = sprintf('%s_%s', $view->parent->vars['id'], $name); $fullName = sprintf('%s[%s]', $parentFullName, $name); $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName); } else { $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; } if (!$translationDomain) { $translationDomain = $view->parent->vars['translation_domain']; } } else { $id = $name; $fullName = $name; $uniqueBlockPrefix = '_'.$blockName; // Strip leading underscores and digits. These are allowed in // form names, but not in HTML4 ID attributes. // http://www.w3.org/TR/html401/struct/global.html#adef-id $id = ltrim($id, '_0123456789'); } $blockPrefixes = array(); for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) { array_unshift($blockPrefixes, $type->getName()); } $blockPrefixes[] = $uniqueBlockPrefix; if (!$translationDomain) { $translationDomain = 'messages'; } $view->vars = array_replace($view->vars, array( 'form' => $view, 'id' => $id, 'name' => $name, 'full_name' => $fullName, 'disabled' => $form->isDisabled(), 'label' => $options['label'], 'multipart' => false, 'attr' => $options['attr'], 'block_prefixes' => $blockPrefixes, 'unique_block_prefix' => $uniqueBlockPrefix, 'translation_domain' => $translationDomain, // Using the block name here speeds up performance in collection // forms, where each entry has the same full block name. // Including the type is important too, because if rows of a // collection form have different types (dynamically), they should // be rendered differently. // https://github.com/symfony/symfony/issues/5038 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'block_name' => null, 'disabled' => false, 'label' => null, 'attr' => array(), 'translation_domain' => null, 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( 'attr' => 'array', )); } } PK!Z^^#Extension/Core/Type/PercentType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class PercentType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['precision'], $options['type'])); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 0, 'type' => 'fractional', 'compound' => false, )); $resolver->setAllowedValues(array( 'type' => array( 'fractional', 'integer', ), )); } /** * {@inheritdoc} */ public function getName() { return 'percent'; } } PK!TT$Extension/Core/Type/CheckboxType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CheckboxType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { // Unlike in other types, where the data is NULL by default, it // needs to be a Boolean here. setData(null) is not acceptable // for checkboxes and radio buttons (unless a custom model // transformer handles this case). // We cannot solve this case via overriding the "data" option, because // doing so also calls setDataLocked(true). $builder->setData(isset($options['data']) ? $options['data'] : false); $builder->addViewTransformer(new BooleanToStringTransformer($options['value'])); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'value' => $options['value'], 'checked' => null !== $form->getViewData(), )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $emptyData = function (FormInterface $form, $viewData) { return $viewData; }; $resolver->setDefaults(array( 'value' => '1', 'empty_data' => $emptyData, 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'checkbox'; } } PK!&ߏvv$Extension/Core/Type/BirthdayType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class BirthdayType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'years' => range(date('Y') - 120, date('Y')), )); } /** * {@inheritdoc} */ public function getParent() { return 'date'; } /** * {@inheritdoc} */ public function getName() { return 'birthday'; } } PK!7pOLL!Extension/Core/Type/RadioType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class RadioType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'checkbox'; } /** * {@inheritdoc} */ public function getName() { return 'radio'; } } PK!Goo Extension/Core/Type/FileType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FileType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'type' => 'file', 'value' => '', )); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $view ->vars['multipart'] = true ; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, 'data_class' => 'Symfony\Component\HttpFoundation\File\File', 'empty_data' => null, )); } /** * {@inheritdoc} */ public function getName() { return 'file'; } } PK!8JJ"Extension/Core/Type/SearchType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class SearchType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'search'; } } PK!_LL$Extension/Core/Type/TimezoneType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TimezoneType extends AbstractType { /** * Stores the available timezone choices * @var array */ private static $timezones; /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => self::getTimezones(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'timezone'; } /** * Returns the timezone choices. * * The choices are generated from the ICU function * \DateTimeZone::listIdentifiers(). They are cached during a single request, * so multiple timezone fields on the same page don't lead to unnecessary * overhead. * * @return array The timezone choices */ public static function getTimezones() { if (null === static::$timezones) { static::$timezones = array(); foreach (\DateTimeZone::listIdentifiers() as $timezone) { $parts = explode('/', $timezone); if (count($parts) > 2) { $region = $parts[0]; $name = $parts[1].' - '.$parts[2]; } elseif (count($parts) > 1) { $region = $parts[0]; $name = $parts[1]; } else { $region = 'Other'; $name = $parts[0]; } static::$timezones[$region][$timezone] = str_replace('_', ' ', $name); } } return static::$timezones; } } PK!HH!Extension/Core/Type/EmailType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; class EmailType extends AbstractType { /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'email'; } } PK![Gԃ &Extension/Core/Type/CollectionType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CollectionType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { if ($options['allow_add'] && $options['prototype']) { $prototype = $builder->create($options['prototype_name'], $options['type'], array_replace(array( 'label' => $options['prototype_name'].'label__', ), $options['options'])); $builder->setAttribute('prototype', $prototype->getForm()); } $resizeListener = new ResizeFormListener( $options['type'], $options['options'], $options['allow_add'], $options['allow_delete'] ); $builder->addEventSubscriber($resizeListener); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'allow_add' => $options['allow_add'], 'allow_delete' => $options['allow_delete'], )); if ($form->getConfig()->hasAttribute('prototype')) { $view->vars['prototype'] = $form->getConfig()->getAttribute('prototype')->createView($view); } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { if ($form->getConfig()->hasAttribute('prototype') && $view->vars['prototype']->vars['multipart']) { $view->vars['multipart'] = true; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $optionsNormalizer = function (Options $options, $value) { $value['block_name'] = 'entry'; return $value; }; $resolver->setDefaults(array( 'allow_add' => false, 'allow_delete' => false, 'prototype' => true, 'prototype_name' => '__name__', 'type' => 'text', 'options' => array(), )); $resolver->setNormalizers(array( 'options' => $optionsNormalizer, )); } /** * {@inheritdoc} */ public function getName() { return 'collection'; } } PK!tII$Extension/Core/Type/TextareaType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; class TextareaType extends AbstractType { /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['pattern'] = null; } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'textarea'; } } PK!$Extension/Core/Type/LanguageType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LanguageType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getLanguageBundle()->getLanguageNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'language'; } } PK!T; Extension/Core/Type/TextType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TextType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'text'; } } PK!H?!a Extension/Core/Type/TimeType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class TimeType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $parts = array('hour'); $format = 'H'; if ($options['with_seconds'] && !$options['with_minutes']) { throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.'); } if ($options['with_minutes']) { $format .= ':i'; $parts[] = 'minute'; } if ($options['with_seconds']) { $format .= ':s'; $parts[] = 'second'; } if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, ); if ('choice' === $options['widget']) { $hours = $minutes = array(); foreach ($options['hours'] as $hour) { $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT); } // Only pass a subset of the options to children $hourOptions['choices'] = $hours; $hourOptions['empty_value'] = $options['empty_value']['hour']; if ($options['with_minutes']) { foreach ($options['minutes'] as $minute) { $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT); } $minuteOptions['choices'] = $minutes; $minuteOptions['empty_value'] = $options['empty_value']['minute']; } if ($options['with_seconds']) { $seconds = array(); foreach ($options['seconds'] as $second) { $seconds[$second] = str_pad($second, 2, '0', STR_PAD_LEFT); } $secondOptions['choices'] = $seconds; $secondOptions['empty_value'] = $options['empty_value']['second']; } // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { $hourOptions[$passOpt] = $options[$passOpt]; if ($options['with_minutes']) { $minuteOptions[$passOpt] = $options[$passOpt]; } if ($options['with_seconds']) { $secondOptions[$passOpt] = $options[$passOpt]; } } } $builder->add('hour', $options['widget'], $hourOptions); if ($options['with_minutes']) { $builder->add('minute', $options['widget'], $minuteOptions); } if ($options['with_seconds']) { $builder->add('second', $options['widget'], $secondOptions); } $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'])); } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'widget' => $options['widget'], 'with_minutes' => $options['with_minutes'], 'with_seconds' => $options['with_seconds'], )); if ('single_text' === $options['widget']) { $view->vars['type'] = 'time'; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; $emptyValue = $emptyValueDefault = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { if (is_array($emptyValue)) { $default = $emptyValueDefault($options); return array_merge( array('hour' => $default, 'minute' => $default, 'second' => $default), $emptyValue ); } return array( 'hour' => $emptyValue, 'minute' => $emptyValue, 'second' => $emptyValue ); }; $resolver->setDefaults(array( 'hours' => range(0, 23), 'minutes' => range(0, 59), 'seconds' => range(0, 59), 'widget' => 'choice', 'input' => 'datetime', 'with_minutes' => true, 'with_seconds' => false, 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'widget' => array( 'single_text', 'text', 'choice', ), )); } /** * {@inheritdoc} */ public function getName() { return 'time'; } } PK! &''$Extension/Core/Type/DateTimeType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class DateTimeType extends AbstractType { const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM; const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM; /** * This is not quite the HTML5 format yet, because ICU lacks the * capability of parsing and generating RFC 3339 dates, which * are like the below pattern but with a timezone suffix. The * timezone suffix is * * * "Z" for UTC * * "(-|+)HH:mm" for other timezones (note the colon!) * * For more information see: * * http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax * http://www.w3.org/TR/html-markup/input.datetime.html * http://tools.ietf.org/html/rfc3339 * * An ICU ticket was created: * http://icu-project.org/trac/ticket/9421 * * It was supposedly fixed, but is not available in all PHP installations * yet. To temporarily circumvent this issue, DateTimeToRfc3339Transformer * is used when the format matches this constant. */ const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"; private static $acceptedFormats = array( \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $parts = array('year', 'month', 'day', 'hour'); $dateParts = array('year', 'month', 'day'); $timeParts = array('hour'); if ($options['with_minutes']) { $parts[] = 'minute'; $timeParts[] = 'minute'; } if ($options['with_seconds']) { $parts[] = 'second'; $timeParts[] = 'second'; } $dateFormat = is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT; $timeFormat = self::DEFAULT_TIME_FORMAT; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "date_format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); } if ('single_text' === $options['widget']) { if (self::HTML5_FORMAT === $pattern) { $builder->addViewTransformer(new DateTimeToRfc3339Transformer( $options['model_timezone'], $options['view_timezone'] )); } else { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( $options['model_timezone'], $options['view_timezone'], $dateFormat, $timeFormat, $calendar, $pattern )); } } else { // Only pass a subset of the options to children $dateOptions = array_intersect_key($options, array_flip(array( 'years', 'months', 'days', 'empty_value', 'required', 'translation_domain', ))); $timeOptions = array_intersect_key($options, array_flip(array( 'hours', 'minutes', 'seconds', 'with_minutes', 'with_seconds', 'empty_value', 'required', 'translation_domain', ))); if (null !== $options['date_widget']) { $dateOptions['widget'] = $options['date_widget']; } if (null !== $options['time_widget']) { $timeOptions['widget'] = $options['time_widget']; } if (null !== $options['date_format']) { $dateOptions['format'] = $options['date_format']; } $dateOptions['input'] = $timeOptions['input'] = 'array'; $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true; $builder ->addViewTransformer(new DataTransformerChain(array( new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts), new ArrayToPartsTransformer(array( 'date' => $dateParts, 'time' => $timeParts, )), ))) ->add('date', 'date', $dateOptions) ->add('time', 'time', $timeOptions) ; } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'datetime'; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; // Defaults to the value of "widget" $dateWidget = function (Options $options) { return $options['widget']; }; // Defaults to the value of "widget" $timeWidget = function (Options $options) { return $options['widget']; }; $resolver->setDefaults(array( 'input' => 'datetime', 'model_timezone' => null, 'view_timezone' => null, 'format' => self::HTML5_FORMAT, 'date_format' => null, 'widget' => null, 'date_widget' => $dateWidget, 'time_widget' => $timeWidget, 'with_minutes' => true, 'with_seconds' => false, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); // Don't add some defaults in order to preserve the defaults // set in DateType and TimeType $resolver->setOptional(array( 'empty_value', 'years', 'months', 'days', 'hours', 'minutes', 'seconds', )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'date_widget' => array( null, // inherit default from DateType 'single_text', 'text', 'choice', ), 'time_widget' => array( null, // inherit default from TimeType 'single_text', 'text', 'choice', ), // This option will overwrite "date_widget" and "time_widget" options 'widget' => array( null, // default, don't overwrite options 'single_text', 'text', 'choice', ), )); } /** * {@inheritdoc} */ public function getName() { return 'datetime'; } } PK!qExtension/Core/Type/UrlType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class UrlType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol'])); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'default_protocol' => 'http', )); } /** * {@inheritdoc} */ public function getParent() { return 'text'; } /** * {@inheritdoc} */ public function getName() { return 'url'; } } PK!9$Extension/Core/Type/RepeatedType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class RepeatedType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { // Overwrite required option for child fields $options['first_options']['required'] = $options['required']; $options['second_options']['required'] = $options['required']; if (!isset($options['options']['error_bubbling'])) { $options['options']['error_bubbling'] = $options['error_bubbling']; } $builder ->addViewTransformer(new ValueToDuplicatesTransformer(array( $options['first_name'], $options['second_name'], ))) ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'])) ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'])) ; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'type' => 'text', 'options' => array(), 'first_options' => array(), 'second_options' => array(), 'first_name' => 'first', 'second_name' => 'second', 'error_bubbling' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'repeated'; } } PK!M2\3,3, Extension/Core/Type/DateType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\ReversedTransformer; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; class DateType extends AbstractType { const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM; const HTML5_FORMAT = 'yyyy-MM-dd'; private static $acceptedFormats = array( \IntlDateFormatter::FULL, \IntlDateFormatter::LONG, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, ); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $dateFormat = is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT; $timeFormat = \IntlDateFormatter::NONE; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); } if (null !== $pattern && (false === strpos($pattern, 'y') || false === strpos($pattern, 'M') || false === strpos($pattern, 'd'))) { throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" and "d". Its current value is "%s".', $pattern)); } if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( $options['model_timezone'], $options['view_timezone'], $dateFormat, $timeFormat, $calendar, $pattern )); } else { $yearOptions = $monthOptions = $dayOptions = array( 'error_bubbling' => true, ); $formatter = new \IntlDateFormatter( \Locale::getDefault(), $dateFormat, $timeFormat, 'UTC', $calendar, $pattern ); $formatter->setLenient(false); if ('choice' === $options['widget']) { // Only pass a subset of the options to children $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years'])); $yearOptions['empty_value'] = $options['empty_value']['year']; $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months'])); $monthOptions['empty_value'] = $options['empty_value']['month']; $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days'])); $dayOptions['empty_value'] = $options['empty_value']['day']; } // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { $yearOptions[$passOpt] = $monthOptions[$passOpt] = $dayOptions[$passOpt] = $options[$passOpt]; } $builder ->add('year', $options['widget'], $yearOptions) ->add('month', $options['widget'], $monthOptions) ->add('day', $options['widget'], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day') )) ->setAttribute('formatter', $formatter) ; } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day')) )); } } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'date'; } if ($form->getConfig()->hasAttribute('formatter')) { $pattern = $form->getConfig()->getAttribute('formatter')->getPattern(); // remove special characters unless the format was explicitly specified if (!is_string($options['format'])) { $pattern = preg_replace('/[^yMd]+/', '', $pattern); } // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) // lookup various formats at http://userguide.icu-project.org/formatparse/datetime if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) { $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern); } else { // default fallback $pattern = '{{ year }}{{ month }}{{ day }}'; } $view->vars['date_pattern'] = $pattern; } } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $compound = function (Options $options) { return $options['widget'] !== 'single_text'; }; $emptyValue = $emptyValueDefault = function (Options $options) { return $options['required'] ? null : ''; }; $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { if (is_array($emptyValue)) { $default = $emptyValueDefault($options); return array_merge( array('year' => $default, 'month' => $default, 'day' => $default), $emptyValue ); } return array( 'year' => $emptyValue, 'month' => $emptyValue, 'day' => $emptyValue ); }; $format = function (Options $options) { return $options['widget'] === 'single_text' ? DateType::HTML5_FORMAT : DateType::DEFAULT_FORMAT; }; $resolver->setDefaults(array( 'years' => range(date('Y') - 5, date('Y') + 5), 'months' => range(1, 12), 'days' => range(1, 31), 'widget' => 'choice', 'input' => 'datetime', 'format' => $format, 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. 'data_class' => null, 'compound' => $compound, )); $resolver->setNormalizers(array( 'empty_value' => $emptyValueNormalizer, )); $resolver->setAllowedValues(array( 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), 'widget' => array( 'single_text', 'text', 'choice', ), )); $resolver->setAllowedTypes(array( 'format' => array('int', 'string'), )); } /** * {@inheritdoc} */ public function getName() { return 'date'; } private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $timestamps) { $pattern = $formatter->getPattern(); $timezone = $formatter->getTimezoneId(); if ($setTimeZone = method_exists($formatter, 'setTimeZone')) { $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); } if (preg_match($regex, $pattern, $matches)) { $formatter->setPattern($matches[0]); foreach ($timestamps as $key => $timestamp) { $timestamps[$key] = $formatter->format($timestamp); } // I'd like to clone the formatter above, but then we get a // segmentation fault, so let's restore the old state instead $formatter->setPattern($pattern); } if ($setTimeZone) { $formatter->setTimeZone($timezone); } else { $formatter->setTimeZoneId($timezone); } return $timestamps; } private function listYears(array $years) { $result = array(); foreach ($years as $year) { if (false !== $y = gmmktime(0, 0, 0, 6, 15, $year)) { $result[$year] = $y; } } return $result; } private function listMonths(array $months) { $result = array(); foreach ($months as $month) { $result[$month] = gmmktime(0, 0, 0, $month, 15); } return $result; } private function listDays(array $days) { $result = array(); foreach ($days as $day) { $result[$day] = gmmktime(0, 0, 0, 5, $day); } return $result; } } PK!aLŢ#Extension/Core/Type/CountryType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CountryType extends AbstractType { /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'choices' => Intl::getRegionBundle()->getCountryNames(), )); } /** * {@inheritdoc} */ public function getParent() { return 'choice'; } /** * {@inheritdoc} */ public function getName() { return 'country'; } } PK!Ci"Extension/Core/Type/NumberType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class NumberType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer(new NumberToLocalizedStringTransformer( $options['precision'], $options['grouping'], $options['rounding_mode'] )); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, 'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( NumberToLocalizedStringTransformer::ROUND_FLOOR, NumberToLocalizedStringTransformer::ROUND_DOWN, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN, NumberToLocalizedStringTransformer::ROUND_HALF_UP, NumberToLocalizedStringTransformer::ROUND_UP, NumberToLocalizedStringTransformer::ROUND_CEILING, ), )); } /** * {@inheritdoc} */ public function getName() { return 'number'; } } PK!:y   Extension/Core/Type/FormType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; class FormType extends BaseType { /** * @var PropertyAccessorInterface */ private $propertyAccessor; public function __construct(PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); $isDataOptionSet = array_key_exists('data', $options); $builder ->setRequired($options['required']) ->setErrorBubbling($options['error_bubbling']) ->setEmptyData($options['empty_data']) ->setPropertyPath($options['property_path']) ->setMapped($options['mapped']) ->setByReference($options['by_reference']) ->setInheritData($options['inherit_data']) ->setCompound($options['compound']) ->setData($isDataOptionSet ? $options['data'] : null) ->setDataLocked($isDataOptionSet) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ->setMethod($options['method']) ->setAction($options['action']) ; if ($options['trim']) { $builder->addEventSubscriber(new TrimListener()); } } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { parent::buildView($view, $form, $options); $name = $form->getName(); $readOnly = $options['read_only']; if ($view->parent) { if ('' === $name) { throw new LogicException('Form node with empty name can be used only as root form node.'); } // Complex fields are read-only if they themselves or their parents are. if (!$readOnly) { $readOnly = $view->parent->vars['read_only']; } } $view->vars = array_replace($view->vars, array( 'read_only' => $readOnly, 'errors' => $form->getErrors(), 'valid' => $form->isSubmitted() ? $form->isValid() : true, 'value' => $form->getViewData(), 'data' => $form->getNormData(), 'required' => $form->isRequired(), 'max_length' => $options['max_length'], 'pattern' => $options['pattern'], 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), 'method' => $form->getConfig()->getMethod(), 'action' => $form->getConfig()->getAction(), 'submitted' => $form->isSubmitted(), )); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $multipart = false; foreach ($view->children as $child) { if ($child->vars['multipart']) { $multipart = true; break; } } $view->vars['multipart'] = $multipart; } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); // Derive "data_class" option from passed "data" object $dataClass = function (Options $options) { return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null; }; // Derive "empty_data" closure from "data_class" option $emptyData = function (Options $options) { $class = $options['data_class']; if (null !== $class) { return function (FormInterface $form) use ($class) { return $form->isEmpty() && !$form->isRequired() ? null : new $class(); }; } return function (FormInterface $form) { return $form->getConfig()->getCompound() ? array() : ''; }; }; // For any form that is not represented by a single HTML control, // errors should bubble up by default $errorBubbling = function (Options $options) { return $options['compound']; }; // BC with old "virtual" option $inheritData = function (Options $options) { if (null !== $options['virtual']) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED); return $options['virtual']; } return false; }; // If data is given, the form is locked to that data // (independent of its value) $resolver->setOptional(array( 'data', )); $resolver->setDefaults(array( 'data_class' => $dataClass, 'empty_data' => $emptyData, 'trim' => true, 'required' => true, 'read_only' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, 'mapped' => true, 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label_attr' => array(), 'virtual' => null, 'inherit_data' => $inheritData, 'compound' => true, 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references 'action' => '', )); $resolver->setAllowedTypes(array( 'label_attr' => 'array', )); } /** * {@inheritdoc} */ public function getParent() { return null; } /** * {@inheritdoc} */ public function getName() { return 'form'; } } PK!5S !Extension/Core/Type/MoneyType.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class MoneyType extends AbstractType { protected static $patterns = array(); /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->addViewTransformer(new MoneyToLocalizedStringTransformer( $options['precision'], $options['grouping'], null, $options['divisor'] )) ; } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['money_pattern'] = self::getPattern($options['currency']); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 2, 'grouping' => false, 'divisor' => 1, 'currency' => 'EUR', 'compound' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'money'; } /** * Returns the pattern for this locale * * The pattern contains the placeholder "{{ widget }}" where the HTML tag should * be inserted */ protected static function getPattern($currency) { if (!$currency) { return '{{ widget }}'; } $locale = \Locale::getDefault(); if (!isset(self::$patterns[$locale])) { self::$patterns[$locale] = array(); } if (!isset(self::$patterns[$locale][$currency])) { $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); $pattern = $format->formatCurrency('123', $currency); // the spacings between currency symbol and number are ignored, because // a single space leads to better readability in combination with input // fields // the regex also considers non-break spaces (0xC2 or 0xA0 in UTF-8) preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123(?:[,.]0+)?[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/u', $pattern, $matches); if (!empty($matches[1])) { self::$patterns[$locale][$currency] = $matches[1].' {{ widget }}'; } elseif (!empty($matches[2])) { self::$patterns[$locale][$currency] = '{{ widget }} '.$matches[2]; } else { self::$patterns[$locale][$currency] = '{{ widget }}'; } } return self::$patterns[$locale][$currency]; } } PK!6s-Extension/DataCollector/FormDataCollector.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; /** * Data collector for {@link \Symfony\Component\Form\FormInterface} instances. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class FormDataCollector extends DataCollector implements FormDataCollectorInterface { /** * @var FormDataExtractor */ private $dataExtractor; /** * Stores the collected data per {@link FormInterface} instance. * * Uses the hashes of the forms as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormInterface} instances. * * @var array */ private $dataByForm; /** * Stores the collected data per {@link FormView} instance. * * Uses the hashes of the views as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormView} instances. * * @var array */ private $dataByView; /** * Connects {@link FormView} with {@link FormInterface} instances. * * Uses the hashes of the views as keys and the hashes of the forms as * values. This is preferable over storing the objects directly, because * this way they can safely be discarded by the GC. * * @var array */ private $formsByView; public function __construct(FormDataExtractorInterface $dataExtractor) { $this->dataExtractor = $dataExtractor; $this->data = array( 'forms' => array(), 'nb_errors' => 0, ); } /** * Does nothing. The data is collected during the form event listeners. */ public function collect(Request $request, Response $response, \Exception $exception = null) { } /** * {@inheritdoc} */ public function associateFormWithView(FormInterface $form, FormView $view) { $this->formsByView[spl_object_hash($view)] = spl_object_hash($form); } /** * {@inheritdoc} */ public function collectConfiguration(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractConfiguration($form) ); foreach ($form as $child) { $this->collectConfiguration($child); } } /** * {@inheritdoc} */ public function collectDefaultData(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractDefaultData($form) ); foreach ($form as $child) { $this->collectDefaultData($child); } } /** * {@inheritdoc} */ public function collectSubmittedData(FormInterface $form) { $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { $this->dataByForm[$hash] = array(); } $this->dataByForm[$hash] = array_replace( $this->dataByForm[$hash], $this->dataExtractor->extractSubmittedData($form) ); // Count errors if (isset($this->dataByForm[$hash]['errors'])) { $this->data['nb_errors'] += count($this->dataByForm[$hash]['errors']); } foreach ($form as $child) { $this->collectSubmittedData($child); } } /** * {@inheritdoc} */ public function collectViewVariables(FormView $view) { $hash = spl_object_hash($view); if (!isset($this->dataByView[$hash])) { $this->dataByView[$hash] = array(); } $this->dataByView[$hash] = array_replace( $this->dataByView[$hash], $this->dataExtractor->extractViewVariables($view) ); foreach ($view->children as $child) { $this->collectViewVariables($child); } } /** * {@inheritdoc} */ public function buildPreliminaryFormTree(FormInterface $form) { $this->data['forms'][$form->getName()] = array(); $this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()]); } /** * {@inheritdoc} */ public function buildFinalFormTree(FormInterface $form, FormView $view) { $this->data['forms'][$form->getName()] = array(); $this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()]); } /** * {@inheritDoc} */ public function getName() { return 'form'; } /** * {@inheritdoc} */ public function getData() { return $this->data; } private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output = null) { $hash = spl_object_hash($form); $output = isset($this->dataByForm[$hash]) ? $this->dataByForm[$hash] : array(); $output['children'] = array(); foreach ($form as $name => $child) { $output['children'][$name] = array(); $this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name]); } } private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output = null) { $viewHash = spl_object_hash($view); $formHash = null; if (null !== $form) { $formHash = spl_object_hash($form); } elseif (isset($this->formsByView[$viewHash])) { // The FormInterface instance of the CSRF token is never contained in // the FormInterface tree of the form, so we need to get the // corresponding FormInterface instance for its view in a different way $formHash = $this->formsByView[$viewHash]; } $output = isset($this->dataByView[$viewHash]) ? $this->dataByView[$viewHash] : array(); if (null !== $formHash) { $output = array_replace( $output, isset($this->dataByForm[$formHash]) ? $this->dataByForm[$formHash] : array() ); } $output['children'] = array(); foreach ($view->children as $name => $childView) { // The CSRF token, for example, is never added to the form tree. // It is only present in the view. $childForm = null !== $form && $form->has($name) ? $form->get($name) : null; $output['children'][$name] = array(); $this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name]); } } } PK!I2  ?Extension/DataCollector/EventListener/DataCollectorListener.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; /** * Listener that invokes a data collector for the {@link FormEvents::POST_SET_DATA} * and {@link FormEvents::POST_SUBMIT} events. * * @since 2.4 * @author Bernhard Schussek */ class DataCollectorListener implements EventSubscriberInterface { /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(FormDataCollectorInterface $dataCollector) { $this->dataCollector = $dataCollector; } /** * {@inheritDoc} */ public static function getSubscribedEvents() { return array( // High priority in order to be called as soon as possible FormEvents::POST_SET_DATA => array('postSetData', 255), // Low priority in order to be called as late as possible FormEvents::POST_SUBMIT => array('postSubmit', -255), ); } /** * Listener for the {@link FormEvents::POST_SET_DATA} event. * * @param FormEvent $event The event object */ public function postSetData(FormEvent $event) { if ($event->getForm()->isRoot()) { // Collect basic information about each form $this->dataCollector->collectConfiguration($event->getForm()); // Collect the default data $this->dataCollector->collectDefaultData($event->getForm()); } } /** * Listener for the {@link FormEvents::POST_SUBMIT} event. * * @param FormEvent $event The event object */ public function postSubmit(FormEvent $event) { if ($event->getForm()->isRoot()) { // Collect the submitted data of each form $this->dataCollector->collectSubmittedData($event->getForm()); // Assemble a form tree // This is done again in collectViewVariables(), but that method // is not guaranteed to be called (i.e. when no view is created) $this->dataCollector->buildPreliminaryFormTree($event->getForm()); } } } PK!T 6Extension/DataCollector/FormDataCollectorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; /** * Collects and structures information about forms. * * @since 2.4 * @author Bernhard Schussek */ interface FormDataCollectorInterface extends DataCollectorInterface { /** * Stores configuration data of the given form and its children. * * @param FormInterface $form A root form */ public function collectConfiguration(FormInterface $form); /** * Stores the default data of the given form and its children. * * @param FormInterface $form A root form */ public function collectDefaultData(FormInterface $form); /** * Stores the submitted data of the given form and its children. * * @param FormInterface $form A root form */ public function collectSubmittedData(FormInterface $form); /** * Stores the view variables of the given form view and its children. * * @param FormView $view A root form view */ public function collectViewVariables(FormView $view); /** * Specifies that the given objects represent the same conceptual form. * * @param FormInterface $form A form object * @param FormView $view A view object */ public function associateFormWithView(FormInterface $form, FormView $view); /** * Assembles the data collected about the given form and its children as * a tree-like data structure. * * The result can be queried using {@link getData()}. * * @param FormInterface $form A root form */ public function buildPreliminaryFormTree(FormInterface $form); /** * Assembles the data collected about the given form and its children as * a tree-like data structure. * * The result can be queried using {@link getData()}. * * Contrary to {@link buildPreliminaryFormTree()}, a {@link FormView} * object has to be passed. The tree structure of this view object will be * used for structuring the resulting data. That means, if a child is * present in the view, but not in the form, it will be present in the final * data array anyway. * * When {@link FormView} instances are present in the view tree, for which * no corresponding {@link FormInterface} objects can be found in the form * tree, only the view data will be included in the result. If a * corresponding {@link FormInterface} exists otherwise, call * {@link associateFormWithView()} before calling this method. * * @param FormInterface $form A root form * @param FormView $view A root view */ public function buildFinalFormTree(FormInterface $form, FormView $view); /** * Returns all collected data. * * @return array */ public function getData(); } PK!6Extension/DataCollector/FormDataExtractorInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; /** * Extracts arrays of information out of forms. * * @since 2.4 * @author Bernhard Schussek */ interface FormDataExtractorInterface { /** * Extracts the configuration data of a form. * * @param FormInterface $form The form * * @return array Information about the form's configuration */ public function extractConfiguration(FormInterface $form); /** * Extracts the default data of a form. * * @param FormInterface $form The form * * @return array Information about the form's default data */ public function extractDefaultData(FormInterface $form); /** * Extracts the submitted data of a form. * * @param FormInterface $form The form * * @return array Information about the form's submitted data */ public function extractSubmittedData(FormInterface $form); /** * Extracts the view variables of a form. * * @param FormView $view The form view * * @return array Information about the view's variables */ public function extractViewVariables(FormView $view); } PK!| ]@Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ResolvedFormTypeInterface; /** * Proxy that invokes a data collector when creating a form and its view. * * @since 2.4 * @author Bernhard Schussek */ class ResolvedTypeDataCollectorProxy implements ResolvedFormTypeInterface { /** * @var ResolvedFormTypeInterface */ private $proxiedType; /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(ResolvedFormTypeInterface $proxiedType, FormDataCollectorInterface $dataCollector) { $this->proxiedType = $proxiedType; $this->dataCollector = $dataCollector; } /** * {@inheritdoc} */ public function getName() { return $this->proxiedType->getName(); } /** * {@inheritdoc} */ public function getParent() { return $this->proxiedType->getParent(); } /** * {@inheritdoc} */ public function getInnerType() { return $this->proxiedType->getInnerType(); } /** * {@inheritdoc} */ public function getTypeExtensions() { return $this->proxiedType->getTypeExtensions(); } /** * {@inheritdoc} */ public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $builder = $this->proxiedType->createBuilder($factory, $name, $options); $builder->setAttribute('data_collector/passed_options', $options); $builder->setType($this); return $builder; } /** * {@inheritdoc} */ public function createView(FormInterface $form, FormView $parent = null) { return $this->proxiedType->createView($form, $parent); } /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $this->proxiedType->buildForm($builder, $options); } /** * {@inheritdoc} */ public function buildView(FormView $view, FormInterface $form, array $options) { $this->proxiedType->buildView($view, $form, $options); } /** * {@inheritdoc} */ public function finishView(FormView $view, FormInterface $form, array $options) { $this->proxiedType->finishView($view, $form, $options); // Remember which view belongs to which form instance, so that we can // get the collected data for a view when its form instance is not // available (e.g. CSRF token) $this->dataCollector->associateFormWithView($form, $view); // Since the CSRF token is only present in the FormView tree, we also // need to check the FormView tree instead of calling isRoot() on the // FormInterface tree if (null === $view->parent) { $this->dataCollector->collectViewVariables($view); // Re-assemble data, in case FormView instances were added, for // which no FormInterface instances were present (e.g. CSRF token). // Since finishView() is called after finishing the views of all // children, we can safely assume that information has been // collected about the complete form tree. $this->dataCollector->buildFinalFormTree($form, $view); } } /** * {@inheritdoc} */ public function getOptionsResolver() { return $this->proxiedType->getOptionsResolver(); } } PK!((GExtension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; use Symfony\Component\Form\ResolvedFormTypeInterface; /** * Proxy that wraps resolved types into {@link ResolvedTypeDataCollectorProxy} * instances. * * @since 2.4 * @author Bernhard Schussek */ class ResolvedTypeFactoryDataCollectorProxy implements ResolvedFormTypeFactoryInterface { /** * @var ResolvedFormTypeFactoryInterface */ private $proxiedFactory; /** * @var FormDataCollectorInterface */ private $dataCollector; public function __construct(ResolvedFormTypeFactoryInterface $proxiedFactory, FormDataCollectorInterface $dataCollector) { $this->proxiedFactory = $proxiedFactory; $this->dataCollector = $dataCollector; } /** * {@inheritdoc} */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null) { return new ResolvedTypeDataCollectorProxy( $this->proxiedFactory->createResolvedType($type, $typeExtensions, $parent), $this->dataCollector ); } } PK!#112Extension/DataCollector/DataCollectorExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\AbstractExtension; /** * Extension for collecting data of the forms on a page. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class DataCollectorExtension extends AbstractExtension { /** * @var EventSubscriberInterface */ private $dataCollector; public function __construct(FormDataCollectorInterface $dataCollector) { $this->dataCollector = $dataCollector; } /** * {@inheritDoc} */ protected function loadTypeExtensions() { return array( new Type\DataCollectorTypeExtension($this->dataCollector) ); } } PK!%`-Extension/DataCollector/FormDataExtractor.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; /** * Default implementation of {@link FormDataExtractorInterface}. * * @since 2.4 * @author Bernhard Schussek */ class FormDataExtractor implements FormDataExtractorInterface { /** * @var ValueExporter */ private $valueExporter; /** * Constructs a new data extractor. */ public function __construct(ValueExporter $valueExporter = null) { $this->valueExporter = $valueExporter ?: new ValueExporter(); } /** * {@inheritdoc} */ public function extractConfiguration(FormInterface $form) { $data = array( 'id' => $this->buildId($form), 'type' => $form->getConfig()->getType()->getName(), 'type_class' => get_class($form->getConfig()->getType()->getInnerType()), 'synchronized' => $this->valueExporter->exportValue($form->isSynchronized()), 'passed_options' => array(), 'resolved_options' => array(), ); foreach ($form->getConfig()->getAttribute('data_collector/passed_options', array()) as $option => $value) { $data['passed_options'][$option] = $this->valueExporter->exportValue($value); } foreach ($form->getConfig()->getOptions() as $option => $value) { $data['resolved_options'][$option] = $this->valueExporter->exportValue($value); } ksort($data['passed_options']); ksort($data['resolved_options']); return $data; } /** * {@inheritdoc} */ public function extractDefaultData(FormInterface $form) { $data = array( 'default_data' => array( 'norm' => $this->valueExporter->exportValue($form->getNormData()), ), 'submitted_data' => array(), ); if ($form->getData() !== $form->getNormData()) { $data['default_data']['model'] = $this->valueExporter->exportValue($form->getData()); } if ($form->getViewData() !== $form->getNormData()) { $data['default_data']['view'] = $this->valueExporter->exportValue($form->getViewData()); } return $data; } /** * {@inheritdoc} */ public function extractSubmittedData(FormInterface $form) { $data = array( 'submitted_data' => array( 'norm' => $this->valueExporter->exportValue($form->getNormData()), ), 'errors' => array(), ); if ($form->getViewData() !== $form->getNormData()) { $data['submitted_data']['view'] = $this->valueExporter->exportValue($form->getViewData()); } if ($form->getData() !== $form->getNormData()) { $data['submitted_data']['model'] = $this->valueExporter->exportValue($form->getData()); } foreach ($form->getErrors() as $error) { $data['errors'][] = array( 'message' => $error->getMessage(), ); } $data['synchronized'] = $this->valueExporter->exportValue($form->isSynchronized()); return $data; } /** * {@inheritdoc} */ public function extractViewVariables(FormView $view) { $data = array(); // Set the ID in case no FormInterface object was collected for this // view if (isset($view->vars['id'])) { $data['id'] = $view->vars['id']; } foreach ($view->vars as $varName => $value) { $data['view_vars'][$varName] = $this->valueExporter->exportValue($value); } ksort($data['view_vars']); return $data; } /** * Recursively builds an HTML ID for a form. * * @param FormInterface $form The form * * @return string The HTML ID */ private function buildId(FormInterface $form) { $id = $form->getName(); if (null !== $form->getParent()) { $id = $this->buildId($form->getParent()).'_'.$id; } return $id; } } PK!1 uu;Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DataCollector\Type; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormBuilderInterface; /** * Type extension for collecting data of a form with this type. * * @since 2.4 * @author Robert Schönthal * @author Bernhard Schussek */ class DataCollectorTypeExtension extends AbstractTypeExtension { /** * @var \Symfony\Component\EventDispatcher\EventSubscriberInterface */ private $listener; public function __construct(FormDataCollectorInterface $dataCollector) { $this->listener = new DataCollectorListener($dataCollector); } /** * {@inheritDoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); } /** * {@inheritDoc} */ public function getExtendedType() { return 'form'; } } PK!uUSW W >Extension/DependencyInjection/DependencyInjectionExtension.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Extension\DependencyInjection; use Symfony\Component\Form\FormExtensionInterface; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\ContainerInterface; class DependencyInjectionExtension implements FormExtensionInterface { private $container; private $typeServiceIds; private $typeExtensionServiceIds; private $guesserServiceIds; private $guesser; private $guesserLoaded = false; public function __construct(ContainerInterface $container, array $typeServiceIds, array $typeExtensionServiceIds, array $guesserServiceIds) { $this->container = $container; $this->typeServiceIds = $typeServiceIds; $this->typeExtensionServiceIds = $typeExtensionServiceIds; $this->guesserServiceIds = $guesserServiceIds; } public function getType($name) { if (!isset($this->typeServiceIds[$name])) { throw new InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name)); } $type = $this->container->get($this->typeServiceIds[$name]); if ($type->getName() !== $name) { throw new InvalidArgumentException( sprintf('The type name specified for the service "%s" does not match the actual name. Expected "%s", given "%s"', $this->typeServiceIds[$name], $name, $type->getName() )); } return $type; } public function hasType($name) { return isset($this->typeServiceIds[$name]); } public function getTypeExtensions($name) { $extensions = array(); if (isset($this->typeExtensionServiceIds[$name])) { foreach ($this->typeExtensionServiceIds[$name] as $serviceId) { $extensions[] = $this->container->get($serviceId); } } return $extensions; } public function hasTypeExtensions($name) { return isset($this->typeExtensionServiceIds[$name]); } public function getTypeGuesser() { if (!$this->guesserLoaded) { $this->guesserLoaded = true; $guessers = array(); foreach ($this->guesserServiceIds as $serviceId) { $guessers[] = $this->container->get($serviceId); } if (count($guessers) > 0) { $this->guesser = new FormTypeGuesserChain($guessers); } } return $this->guesser; } } PK!(s //ClickableInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; /** * A clickable form element. * * @author Bernhard Schussek */ interface ClickableInterface { /** * Returns whether this element was clicked. * * @return Boolean Whether this element was clicked. */ public function isClicked(); } PK!H FormView.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; /** * @author Bernhard Schussek */ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The variables assigned to this view. * @var array */ public $vars = array( 'value' => null, 'attr' => array(), ); /** * The parent view. * @var FormView */ public $parent; /** * The child views. * @var array */ public $children = array(); /** * Is the form attached to this renderer rendered? * * Rendering happens when either the widget or the row method was called. * Row implicitly includes widget, however certain rendering mechanisms * have to skip widget rendering when a row is rendered. * * @var Boolean */ private $rendered = false; public function __construct(FormView $parent = null) { $this->parent = $parent; } /** * Returns whether the view was already rendered. * * @return Boolean Whether this view's widget is rendered. */ public function isRendered() { $hasChildren = 0 < count($this->children); if (true === $this->rendered || !$hasChildren) { return $this->rendered; } if ($hasChildren) { foreach ($this->children as $child) { if (!$child->isRendered()) { return false; } } return $this->rendered = true; } return false; } /** * Marks the view as rendered. * * @return FormView The view object. */ public function setRendered() { $this->rendered = true; return $this; } /** * Returns a child by name (implements \ArrayAccess). * * @param string $name The child name * * @return FormView The child view */ public function offsetGet($name) { return $this->children[$name]; } /** * Returns whether the given child exists (implements \ArrayAccess). * * @param string $name The child name * * @return Boolean Whether the child view exists */ public function offsetExists($name) { return isset($this->children[$name]); } /** * Implements \ArrayAccess. * * @throws BadMethodCallException always as setting a child by name is not allowed */ public function offsetSet($name, $value) { throw new BadMethodCallException('Not supported'); } /** * Removes a child (implements \ArrayAccess). * * @param string $name The child name */ public function offsetUnset($name) { unset($this->children[$name]); } /** * Returns an iterator to iterate over children (implements \IteratorAggregate) * * @return \ArrayIterator The iterator */ public function getIterator() { return new \ArrayIterator($this->children); } /** * Implements \Countable. * * @return integer The number of children views */ public function count() { return count($this->children); } } PK! ͋   Forms.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form; use Symfony\Component\Form\Extension\Core\CoreExtension; /** * Entry point of the Form component. * * Use this class to conveniently create new form factories: * * * use Symfony\Component\Form\Forms; * * $formFactory = Forms::createFormFactory(); * * $form = $formFactory->createBuilder() * ->add('firstName', 'text') * ->add('lastName', 'text') * ->add('age', 'integer') * ->add('gender', 'choice', array( * 'choices' => array('m' => 'Male', 'f' => 'Female'), * )) * ->getForm(); * * * You can also add custom extensions to the form factory: * * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new AcmeExtension()) * ->getFormFactory(); * * * If you create custom form types or type extensions, it is * generally recommended to create your own extensions that lazily * load these types and type extensions. In projects where performance * does not matter that much, you can also pass them directly to the * form factory: * * * $formFactory = Forms::createFormFactoryBuilder() * ->addType(new PersonType()) * ->addType(new PhoneNumberType()) * ->addTypeExtension(new FormTypeHelpTextExtension()) * ->getFormFactory(); * * * Support for CSRF protection is provided by the CsrfExtension. * This extension needs a CSRF provider with a strong secret * (e.g. a 20 character long random string). The default * implementation for this is DefaultCsrfProvider: * * * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; * * $secret = 'V8a5Z97e...'; * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new CsrfExtension(new DefaultCsrfProvider($secret))) * ->getFormFactory(); * * * Support for the HttpFoundation is provided by the * HttpFoundationExtension. You are also advised to load the CSRF * extension with the driver for HttpFoundation's Session class: * * * use Symfony\Component\HttpFoundation\Session\Session; * use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; * * $session = new Session(); * $secret = 'V8a5Z97e...'; * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new HttpFoundationExtension()) * ->addExtension(new CsrfExtension(new SessionCsrfProvider($session, $secret))) * ->getFormFactory(); * * * Support for the Validator component is provided by ValidatorExtension. * This extension needs a validator object to function properly: * * * use Symfony\Component\Validator\Validation; * use Symfony\Component\Form\Extension\Validator\ValidatorExtension; * * $validator = Validation::createValidator(); * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new ValidatorExtension($validator)) * ->getFormFactory(); * * * Support for the Templating component is provided by TemplatingExtension. * This extension needs a PhpEngine object for rendering forms. As second * argument you should pass the names of the default themes. Here is an * example for using the default layout with "
" tags: * * * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new TemplatingExtension($engine, null, array( * 'FrameworkBundle:Form', * ))) * ->getFormFactory(); * * * The next example shows how to include the "" layout: * * * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new TemplatingExtension($engine, null, array( * 'FrameworkBundle:Form', * 'FrameworkBundle:FormTable', * ))) * ->getFormFactory(); * * * If you also loaded the CsrfExtension, you should pass the CSRF provider * to the extension so that you can render CSRF tokens in your templates * more easily: * * * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; * * * $secret = 'V8a5Z97e...'; * $csrfProvider = new DefaultCsrfProvider($secret); * $formFactory = Forms::createFormFactoryBuilder() * ->addExtension(new CsrfExtension($csrfProvider)) * ->addExtension(new TemplatingExtension($engine, $csrfProvider, array( * 'FrameworkBundle:Form', * ))) * ->getFormFactory(); * * * @author Bernhard Schussek */ final class Forms { /** * Creates a form factory with the default configuration. * * @return FormFactoryInterface The form factory. */ public static function createFormFactory() { return self::createFormFactoryBuilder()->getFormFactory(); } /** * Creates a form factory builder with the default configuration. * * @return FormFactoryBuilderInterface The form factory builder. */ public static function createFormFactoryBuilder() { $builder = new FormFactoryBuilder(); $builder->addExtension(new CoreExtension()); return $builder; } /** * This class cannot be instantiated. */ private function __construct() { } } PK! 9292form_div_layout.html.twignu[{# Widgets #} {% block form_widget %} {% spaceless %} {% if compound %} {{ block('form_widget_compound') }} {% else %} {{ block('form_widget_simple') }} {% endif %} {% endspaceless %} {% endblock form_widget %} {% block form_widget_simple %} {% spaceless %} {% set type = type|default('text') %} {% endspaceless %} {% endblock form_widget_simple %} {% block form_widget_compound %} {% spaceless %}
{% if form.parent is empty %} {{ form_errors(form) }} {% endif %} {{ block('form_rows') }} {{ form_rest(form) }}
{% endspaceless %} {% endblock form_widget_compound %} {% block collection_widget %} {% spaceless %} {% if prototype is defined %} {% set attr = attr|merge({'data-prototype': form_row(prototype) }) %} {% endif %} {{ block('form_widget') }} {% endspaceless %} {% endblock collection_widget %} {% block textarea_widget %} {% spaceless %} {% endspaceless %} {% endblock textarea_widget %} {% block choice_widget %} {% spaceless %} {% if expanded %} {{ block('choice_widget_expanded') }} {% else %} {{ block('choice_widget_collapsed') }} {% endif %} {% endspaceless %} {% endblock choice_widget %} {% block choice_widget_expanded %} {% spaceless %}
{% for child in form %} {{ form_widget(child) }} {{ form_label(child) }} {% endfor %}
{% endspaceless %} {% endblock choice_widget_expanded %} {% block choice_widget_collapsed %} {% spaceless %} {% if required and empty_value is none and not empty_value_in_choices and not multiple %} {% set required = false %} {% endif %} {% endspaceless %} {% endblock choice_widget_collapsed %} {% block choice_widget_options %} {% spaceless %} {% for group_label, choice in options %} {% if choice is iterable %} {% set options = choice %} {{ block('choice_widget_options') }} {% else %} {% endif %} {% endfor %} {% endspaceless %} {% endblock choice_widget_options %} {% block checkbox_widget %} {% spaceless %} {% endspaceless %} {% endblock checkbox_widget %} {% block radio_widget %} {% spaceless %} {% endspaceless %} {% endblock radio_widget %} {% block datetime_widget %} {% spaceless %} {% if widget == 'single_text' %} {{ block('form_widget_simple') }} {% else %}
{{ form_errors(form.date) }} {{ form_errors(form.time) }} {{ form_widget(form.date) }} {{ form_widget(form.time) }}
{% endif %} {% endspaceless %} {% endblock datetime_widget %} {% block date_widget %} {% spaceless %} {% if widget == 'single_text' %} {{ block('form_widget_simple') }} {% else %}
{{ date_pattern|replace({ '{{ year }}': form_widget(form.year), '{{ month }}': form_widget(form.month), '{{ day }}': form_widget(form.day), })|raw }}
{% endif %} {% endspaceless %} {% endblock date_widget %} {% block time_widget %} {% spaceless %} {% if widget == 'single_text' %} {{ block('form_widget_simple') }} {% else %} {% set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} %}
{{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
{% endif %} {% endspaceless %} {% endblock time_widget %} {% block number_widget %} {% spaceless %} {# type="number" doesn't work with floats #} {% set type = type|default('text') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock number_widget %} {% block integer_widget %} {% spaceless %} {% set type = type|default('number') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock integer_widget %} {% block money_widget %} {% spaceless %} {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }} {% endspaceless %} {% endblock money_widget %} {% block url_widget %} {% spaceless %} {% set type = type|default('url') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock url_widget %} {% block search_widget %} {% spaceless %} {% set type = type|default('search') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock search_widget %} {% block percent_widget %} {% spaceless %} {% set type = type|default('text') %} {{ block('form_widget_simple') }} % {% endspaceless %} {% endblock percent_widget %} {% block password_widget %} {% spaceless %} {% set type = type|default('password') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock password_widget %} {% block hidden_widget %} {% spaceless %} {% set type = type|default('hidden') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock hidden_widget %} {% block email_widget %} {% spaceless %} {% set type = type|default('email') %} {{ block('form_widget_simple') }} {% endspaceless %} {% endblock email_widget %} {% block button_widget %} {% spaceless %} {% if label is empty %} {% set label = name|humanize %} {% endif %} {% endspaceless %} {% endblock button_widget %} {% block submit_widget %} {% spaceless %} {% set type = type|default('submit') %} {{ block('button_widget') }} {% endspaceless %} {% endblock submit_widget %} {% block reset_widget %} {% spaceless %} {% set type = type|default('reset') %} {{ block('button_widget') }} {% endspaceless %} {% endblock reset_widget %} {# Labels #} {% block form_label %} {% spaceless %} {% if label is not sameas(false) %} {% if not compound %} {% set label_attr = label_attr|merge({'for': id}) %} {% endif %} {% if required %} {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} {% endif %} {% if label is empty %} {% set label = name|humanize %} {% endif %} {{ label|trans({}, translation_domain) }} {% endif %} {% endspaceless %} {% endblock form_label %} {% block button_label %}{% endblock %} {# Rows #} {% block repeated_row %} {% spaceless %} {# No need to render the errors here, as all errors are mapped to the first child (see RepeatedTypeValidatorExtension). #} {{ block('form_rows') }} {% endspaceless %} {% endblock repeated_row %} {% block form_row %} {% spaceless %}
{{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }}
{% endspaceless %} {% endblock form_row %} {% block button_row %} {% spaceless %}
{{ form_widget(form) }}
{% endspaceless %} {% endblock button_row %} {% block hidden_row %} {{ form_widget(form) }} {% endblock hidden_row %} {# Misc #} {% block form %} {% spaceless %} {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }} {% endspaceless %} {% endblock form %} {% block form_start %} {% spaceless %} {% set method = method|upper %} {% if method in ["GET", "POST"] %} {% set form_method = method %} {% else %} {% set form_method = "POST" %} {% endif %}
{% if form_method != method %} {% endif %} {% endspaceless %} {% endblock form_start %} {% block form_end %} {% spaceless %} {% if not render_rest is defined or render_rest %} {{ form_rest(form) }} {% endif %} {% endspaceless %} {% endblock form_end %} {% block form_enctype %} {% spaceless %} {% if multipart %}enctype="multipart/form-data"{% endif %} {% endspaceless %} {% endblock form_enctype %} {% block form_errors %} {% spaceless %} {% if errors|length > 0 %}
    {% for error in errors %}
  • {{ error.message }}
  • {% endfor %}
{% endif %} {% endspaceless %} {% endblock form_errors %} {% block form_rest %} {% spaceless %} {% for child in form %} {% if not child.rendered %} {{ form_row(child) }} {% endif %} {% endfor %} {% endspaceless %} {% endblock form_rest %} {# Support #} {% block form_rows %} {% spaceless %} {% for child in form %} {{ form_row(child) }} {% endfor %} {% endspaceless %} {% endblock form_rows %} {% block widget_attributes %} {% spaceless %} id="{{ id }}" name="{{ full_name }}" {%- if read_only %} readonly="readonly"{% endif -%} {%- if disabled %} disabled="disabled"{% endif -%} {%- if required %} required="required"{% endif -%} {%- if max_length %} maxlength="{{ max_length }}"{% endif -%} {%- if pattern %} pattern="{{ pattern }}"{% endif -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is sameas(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not sameas(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {% endspaceless %} {% endblock widget_attributes %} {% block widget_container_attributes %} {% spaceless %} {%- if id is not empty %}id="{{ id }}"{% endif -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is sameas(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not sameas(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {% endspaceless %} {% endblock widget_container_attributes %} {% block button_attributes %} {% spaceless %} id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%} {%- for attrname, attrvalue in attr -%} {{- " " -}} {%- if attrname in ['placeholder', 'title'] -%} {{- attrname }}="{{ attrvalue|trans({}, translation_domain) }}" {%- elseif attrvalue is sameas(true) -%} {{- attrname }}="{{ attrname }}" {%- elseif attrvalue is not sameas(false) -%} {{- attrname }}="{{ attrvalue }}" {%- endif -%} {%- endfor -%} {% endspaceless %} {% endblock button_attributes %} PK![[form_table_layout.html.twignu[{% use "form_div_layout.html.twig" %} {% block form_row %} {% spaceless %}
{% endspaceless %} {% endblock form_row %} {% block button_row %} {% spaceless %} {% endspaceless %} {% endblock button_row %} {% block hidden_row %} {% spaceless %} {% endspaceless %} {% endblock hidden_row %} {% block form_widget_compound %} {% spaceless %}
{{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }}
{{ form_widget(form) }}
{{ form_widget(form) }}
{% if form.parent is empty and errors|length > 0 %} {% endif %} {{ block('form_rows') }} {{ form_rest(form) }}
{{ form_errors(form) }}
{% endspaceless %} {% endblock form_widget_compound %} PK!vqTwigRenderer.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * @author Bernhard Schussek */ class TwigRenderer extends FormRenderer implements TwigRendererInterface { /** * @var TwigRendererEngineInterface */ private $engine; public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); } parent::__construct($engine, $csrfTokenManager); $this->engine = $engine; } /** * {@inheritdoc} */ public function setEnvironment(\Twig_Environment $environment) { $this->engine->setEnvironment($environment); } } PK!b3}}TwigRendererEngineInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRendererEngineInterface; /** * @author Bernhard Schussek */ interface TwigRendererEngineInterface extends FormRendererEngineInterface { /** * Sets Twig's environment. * * @param \Twig_Environment $environment */ public function setEnvironment(\Twig_Environment $environment); } PK!QkkTwigRendererInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRendererInterface; /** * @author Bernhard Schussek */ interface TwigRendererInterface extends FormRendererInterface { /** * Sets Twig's environment. * * @param \Twig_Environment $environment */ public function setEnvironment(\Twig_Environment $environment); } PK!<TwigRendererEngine.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\FormView; /** * @author Bernhard Schussek */ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererEngineInterface { /** * @var \Twig_Environment */ private $environment; /** * @var \Twig_Template */ private $template; /** * {@inheritdoc} */ public function setEnvironment(\Twig_Environment $environment) { $this->environment = $environment; } /** * {@inheritdoc} */ public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; $context = $this->environment->mergeGlobals($variables); ob_start(); // By contract,This method can only be called after getting the resource // (which is passed to the method). Getting a resource for the first time // (with an empty cache) is guaranteed to invoke loadResourcesFromTheme(), // where the property $template is initialized. // We do not call renderBlock here to avoid too many nested level calls // (XDebug limits the level to 100 by default) $this->template->displayBlock($blockName, $context, $this->resources[$cacheKey]); return ob_get_clean(); } /** * Loads the cache with the resource for a given block name. * * This implementation eagerly loads all blocks of the themes assigned to the given view * and all of its ancestors views. This is necessary, because Twig receives the * list of blocks later. At that point, all blocks must already be loaded, for the * case that the function "block()" is used in the Twig template. * * @see getResourceForBlock() * * @param string $cacheKey The cache key of the form view. * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * * @return Boolean True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { // The caller guarantees that $this->resources[$cacheKey][$block] is // not set, but it doesn't have to check whether $this->resources[$cacheKey] // is set. If $this->resources[$cacheKey] is set, all themes for this // $cacheKey are already loaded (due to the eager population, see doc comment). if (isset($this->resources[$cacheKey])) { // As said in the previous, the caller guarantees that // $this->resources[$cacheKey][$block] is not set. Since the themes are // already loaded, it can only be a non-existing block. $this->resources[$cacheKey][$blockName] = false; return false; } // Recursively try to find the block in the themes assigned to $view, // then of its parent view, then of the parent view of the parent and so on. // When the root view is reached in this recursion, also the default // themes are taken into account. // Check each theme whether it contains the searched block if (isset($this->themes[$cacheKey])) { for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { $this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]); // CONTINUE LOADING (see doc comment) } } // Check the default themes once we reach the root view without success if (!$view->parent) { for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]); // CONTINUE LOADING (see doc comment) } } // Proceed with the themes of the parent view if ($view->parent) { $parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR]; if (!isset($this->resources[$parentCacheKey])) { $this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName); } // EAGER CACHE POPULATION (see doc comment) foreach ($this->resources[$parentCacheKey] as $nestedBlockName => $resource) { if (!isset($this->resources[$cacheKey][$nestedBlockName])) { $this->resources[$cacheKey][$nestedBlockName] = $resource; } } } // Even though we loaded the themes, it can happen that none of them // contains the searched block if (!isset($this->resources[$cacheKey][$blockName])) { // Cache that we didn't find anything to speed up further accesses $this->resources[$cacheKey][$blockName] = false; } return false !== $this->resources[$cacheKey][$blockName]; } /** * Loads the resources for all blocks in a theme. * * @param string $cacheKey The cache key for storing the resource. * @param mixed $theme The theme to load the block from. This parameter * is passed by reference, because it might be necessary * to initialize the theme first. Any changes made to * this variable will be kept and be available upon * further calls to this method using the same theme. */ protected function loadResourcesFromTheme($cacheKey, &$theme) { if (!$theme instanceof \Twig_Template) { /* @var \Twig_Template $theme */ $theme = $this->environment->loadTemplate($theme); } if (null === $this->template) { // Store the first \Twig_Template instance that we find so that // we can call displayBlock() later on. It doesn't matter *which* // template we use for that, since we pass the used blocks manually // anyway. $this->template = $theme; } // Use a separate variable for the inheritance traversal, because // theme is a reference and we don't want to change it. $currentTheme = $theme; $context = $this->environment->mergeGlobals(array()); // The do loop takes care of template inheritance. // Add blocks from all templates in the inheritance tree, but avoid // overriding blocks already set. do { foreach ($currentTheme->getBlocks() as $block => $blockData) { if (!isset($this->resources[$cacheKey][$block])) { // The resource given back is the key to the bucket that // contains this block. $this->resources[$cacheKey][$block] = $blockData; } } } while (false !== $currentTheme = $currentTheme->getParent($context)); } } PK! 9,DoctrineOrmExtension.phpnu[PK!01EventListener/MergeDoctrineCollectionListener.phpnu[PK!!%d==$ ChoiceList/EntityLoaderInterface.phpnu[PK! ?x77tChoiceList/EntityChoiceList.phpnu[PK!GCt $_FChoiceList/ORMQueryBuilderLoader.phpnu[PK!`. qppRDoctrineOrmTypeGuesser.phpnu[PK!CiPP0CjDataTransformer/CollectionToArrayTransformer.phpnu[PK!憝qType/EntityType.phpnu[PK!S;,:uType/DoctrineType.phpnu[PK!)..FormRenderer.phpnu[PK!C ButtonTypeInterface.phpnu[PK!K'$FormBuilder.phpnu[PK!&"̰TTFormConfigBuilder.phpnu[PK!E1'5SubmitButtonTypeInterface.phpnu[PK!d87FormRegistry.phpnu[PK!ÊM'%% JFormConfigInterface.phpnu[PK!@ @ ucFormTypeGuesserChain.phpnu[PK!RnGuess/ValueGuess.phpnu[PK!51 1  sGuess/Guess.phpnu[PK!  Guess/TypeGuess.phpnu[PK!0\ZZCallbackTransformer.phpnu[PK!4Nz"z" Button.phpnu[PK!-9NNHautoloader.phpnu[PK!/ttԲFormEvents.phpnu[PK! FormTypeInterface.phpnu[PK!>aFormRegistryInterface.phpnu[PK!?zzLFormTypeGuesserInterface.phpnu[PK!*ResolvedFormType.phpnu[PK!ObXqqDSubmitButton.phpnu[PK!pAbstractRendererEngine.phpnu[PK!DjNAbstractExtension.phpnu[PK!f#jKk'FormRendererEngineInterface.phpnu[PK!11QCForm.phpnu[PK!di$Exception/BadMethodCallException.phpnu[PK!W  #Exception/AlreadyBoundException.phpnu[PK!(dd+]Exception/InvalidConfigurationException.phpnu[PK!_c==%Exception/UnexpectedTypeException.phpnu[PK!SD+Exception/TransformationFailedException.phpnu[PK!é"Exception/OutOfBoundsException.phpnu[PK!yu  Exception/ExceptionInterface.phpnu[PK!NException/RuntimeException.phpnu[PK!K9'2Exception/AlreadySubmittedException.phpnu[PK!1;TT#}Exception/ErrorMappingException.phpnu[PK!+RR!$Exception/StringCastException.phpnu[PK!XException/LogicException.phpnu[PK!gBz&Exception/InvalidArgumentException.phpnu[PK!1886AbstractType.phpnu[PK!I 66Util/OrderedHashMap.phpnu[PK!h''+Util/OrderedHashMapIterator.phpnu[PK!F22! Util/VirtualFormAwareIterator.phpnu[PK!y$$$Util/FormUtil.phpnu[PK!<!Util/InheritDataAwareIterator.phpnu[PK!QTppSubmitButtonBuilder.phpnu[PK!z5}ResolvedFormTypeFactory.phpnu[PK!Sf ZPreloadedExtension.phpnu[PK!>*ii'FormFactory.phpnu[PK!\gU<RequestHandlerInterface.phpnu[PK!+qDAA Resources/translations/validators.pl.xlfnu[PK! (BResources/translations/validators.pt.xlfnu[PK!%(FResources/translations/validators.lv.xlfnu[PK!္o33-'KResources/translations/validators.sr_Cyrl.xlfnu[PK!(OResources/translations/validators.fi.xlfnu[PK!0h(SResources/translations/validators.es.xlfnu[PK!TI(XResources/translations/validators.de.xlfnu[PK!!aZ(V\Resources/translations/validators.it.xlfnu[PK! !(g`Resources/translations/validators.ca.xlfnu[PK!(dResources/translations/validators.mn.xlfnu[PK!-(hResources/translations/validators.ru.xlfnu[PK!3Ե^^(mResources/translations/validators.bg.xlfnu[PK!Ed(rResources/translations/validators.ro.xlfnu[PK!O(vResources/translations/validators.nl.xlfnu[PK!S*(zResources/translations/validators.et.xlfnu[PK!V5(~Resources/translations/validators.fa.xlfnu[PK!q(SResources/translations/validators.id.xlfnu[PK! (iResources/translations/validators.cs.xlfnu[PK!8,:+vResources/translations/validators.zh_CN.xlfnu[PK!Hq(ZResources/translations/validators.lt.xlfnu[PK!_8([Resources/translations/validators.fr.xlfnu[PK!A4(Resources/translations/validators.gl.xlfnu[PK! b8(Resources/translations/validators.hr.xlfnu[PK!WgUugg(şResources/translations/validators.nb.xlfnu[PK!ٻ||(Resources/translations/validators.eu.xlfnu[PK!4@+XResources/translations/validators.pt_BR.xlfnu[PK!5(tResources/translations/validators.sl.xlfnu[PK!*{(yResources/translations/validators.lb.xlfnu[PK!be@(γResources/translations/validators.hu.xlfnu[PK!_Π(Resources/translations/validators.el.xlfnu[PK!X(ϼResources/translations/validators.da.xlfnu[PK!(Resources/translations/validators.ja.xlfnu[PK!s>ll(Resources/translations/validators.sv.xlfnu[PK!y99(Resources/translations/validators.hy.xlfnu[PK!|C(/Resources/translations/validators.ar.xlfnu[PK!r-Resources/translations/validators.sr_Latn.xlfnu[PK!NP\(Resources/translations/validators.he.xlfnu[PK!xfh..Resources/config/validation.xmlnu[PK!R}jjDataMapperInterface.phpnu[PK!s FormInterface.phpnu[PK!" FormEvent.phpnu[PK!=MMFormTypeExtensionInterface.phpnu[PK!}p  8FormError.phpnu[PK! xNativeRequestHandler.phpnu[PK!*8/Extension/Validator/EventListener/ValidationListener.phpnu[PK!Ck)7Extension/Validator/Util/ServerParams.phpnu[PK!2=[<((*>Extension/Validator/ValidatorExtension.phpnu[PK!}>ُ( FExtension/Validator/Constraints/Form.phpnu[PK!-P1HExtension/Validator/Constraints/FormValidator.phpnu[PK!lCt*t*,dExtension/Validator/ValidatorTypeGuesser.phpnu[PK!ɥS=Extension/Validator/ViolationMapper/ViolationPathIterator.phpnu[PK!\T4Extension/Validator/ViolationMapper/RelativePath.phpnu[PK!C_hU+U+7Extension/Validator/ViolationMapper/ViolationMapper.phpnu[PK!kt==@Extension/Validator/ViolationMapper/ViolationMapperInterface.phpnu[PK!-!!5TExtension/Validator/ViolationMapper/ViolationPath.phpnu[PK!f 3Extension/Validator/ViolationMapper/MappingRule.phpnu[PK!3Extension/Validator/Type/BaseValidatorExtension.phpnu[PK!eBR 7/Extension/Validator/Type/FormTypeValidatorExtension.phpnu[PK!͚>@@;nExtension/Validator/Type/RepeatedTypeValidatorExtension.phpnu[PK!19Extension/Validator/Type/SubmitTypeValidatorExtension.phpnu[PK!,QQ,Extension/Templating/TemplatingExtension.phpnu[PK!զY1J Extension/Templating/TemplatingRendererEngine.phpnu[PK!䋧 >Extension/HttpFoundation/EventListener/BindRequestListener.phpnu[PK!j= = 9'Extension/HttpFoundation/HttpFoundationRequestHandler.phpnu[PK!Q4J2Extension/HttpFoundation/HttpFoundationExtension.phpnu[PK!PffAT5Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.phpnu[PK!"q +;Extension/Csrf/CsrfExtension.phpnu[PK!C3?DExtension/Csrf/CsrfProvider/DefaultCsrfProvider.phpnu[PK![^3VMExtension/Csrf/CsrfProvider/SessionCsrfProvider.phpnu[PK!%G5MTExtension/Csrf/CsrfProvider/CsrfProviderInterface.phpnu[PK!3x\Extension/Csrf/CsrfProvider/CsrfProviderAdapter.phpnu[PK!R'WTT7cExtension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.phpnu[PK!?oo7ziExtension/Csrf/EventListener/CsrfValidationListener.phpnu[PK! f-PxExtension/Csrf/Type/FormTypeCsrfExtension.phpnu[PK!CW Extension/Core/CoreExtension.phpnu[PK!:AA-Extension/Core/EventListener/TrimListener.phpnu[PK!õe8UExtension/Core/EventListener/MergeCollectionListener.phpnu[PK!>Q?7OExtension/Core/EventListener/FixUrlProtocolListener.phpnu[PK!b 9MExtension/Core/EventListener/FixCheckboxInputListener.phpnu[PK!\//3@Extension/Core/EventListener/ResizeFormListener.phpnu[PK!?D6Extension/Core/EventListener/FixRadioInputListener.phpnu[PK!jю.Extension/Core/ChoiceList/SimpleChoiceList.phpnu[PK! ##. Extension/Core/ChoiceList/ObjectChoiceList.phpnu[PK!l_R(1Extension/Core/ChoiceList/ChoiceListInterface.phpnu[PK!В4 4 ,#Extension/Core/ChoiceList/LazyChoiceList.phpnu[PK!'ç??(1Extension/Core/ChoiceList/ChoiceList.phpnu[PK!&PP"rqExtension/Core/View/ChoiceView.phpnu[PK!  0vExtension/Core/DataMapper/PropertyPathMapper.phpnu[PK!O###EExtension/Core/DataTransformer/NumberToLocalizedStringTransformer.phpnu[PK!)b""GExtension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.phpnu[PK!e^  ?#Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.phpnu[PK!Þ AExtension/Core/DataTransformer/DateTimeToTimestampTransformer.phpnu[PK!c8V 7Extension/Core/DataTransformer/DataTransformerChain.phpnu[PK!;ddFExtension/Core/DataTransformer/PercentToLocalizedStringTransformer.phpnu[PK!Ze  =~Extension/Core/DataTransformer/DateTimeToArrayTransformer.phpnu[PK!Lpx&&BExtension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.phpnu[PK!  ?Extension/Core/DataTransformer/ValueToDuplicatesTransformer.phpnu[PK!'tqk55C !Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.phpnu[PK!gg=/Extension/Core/DataTransformer/ChoicesToValuesTransformer.phpnu[PK!UdqF8Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.phpnu[PK!ΎgW >>Extension/Core/DataTransformer/DateTimeToStringTransformer.phpnu[PK!"h;^Extension/Core/DataTransformer/ChoiceToValueTransformer.phpnu[PK!H  :fExtension/Core/DataTransformer/ArrayToPartsTransformer.phpnu[PK!/C:oExtension/Core/DataTransformer/BaseDateTimeTransformer.phpnu[PK!T=xExtension/Core/DataTransformer/BooleanToStringTransformer.phpnu[PK!]yD D D9Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.phpnu[PK!/++"Extension/Core/Type/ChoiceType.phpnu[PK!h"Extension/Core/Type/ButtonType.phpnu[PK!DU"8Extension/Core/Type/SubmitType.phpnu[PK!񍢸$gExtension/Core/Type/CurrencyType.phpnu[PK!Ѝ'"bExtension/Core/Type/HiddenType.phpnu[PK!D"^Extension/Core/Type/LocaleType.phpnu[PK!uƵ``#tExtension/Core/Type/IntegerType.phpnu[PK!a!'Extension/Core/Type/ResetType.phpnu[PK!옇$bExtension/Core/Type/PasswordType.phpnu[PK!ٝGG Extension/Core/Type/BaseType.phpnu[PK!Z^^#Extension/Core/Type/PercentType.phpnu[PK!TT$Extension/Core/Type/CheckboxType.phpnu[PK!&ߏvv$qExtension/Core/Type/BirthdayType.phpnu[PK!7pOLL!; Extension/Core/Type/RadioType.phpnu[PK!Goo  Extension/Core/Type/FileType.phpnu[PK!8JJ" Extension/Core/Type/SearchType.phpnu[PK!_LL$3 Extension/Core/Type/TimezoneType.phpnu[PK!HH! Extension/Core/Type/EmailType.phpnu[PK![Gԃ &l Extension/Core/Type/CollectionType.phpnu[PK!tII$o" Extension/Core/Type/TextareaType.phpnu[PK!$ & Extension/Core/Type/LanguageType.phpnu[PK!T; * Extension/Core/Type/TextType.phpnu[PK!H?!a C- Extension/Core/Type/TimeType.phpnu[PK! &''$L Extension/Core/Type/DateTimeType.phpnu[PK!qut Extension/Core/Type/UrlType.phpnu[PK!9$y Extension/Core/Type/RepeatedType.phpnu[PK!M2\3,3,  Extension/Core/Type/DateType.phpnu[PK!aLŢ#e Extension/Core/Type/CountryType.phpnu[PK!Ci"Z Extension/Core/Type/NumberType.phpnu[PK!:y    Extension/Core/Type/FormType.phpnu[PK!5S ! Extension/Core/Type/MoneyType.phpnu[PK!6s- Extension/DataCollector/FormDataCollector.phpnu[PK!I2  ? Extension/DataCollector/EventListener/DataCollectorListener.phpnu[PK!T 6_ Extension/DataCollector/FormDataCollectorInterface.phpnu[PK!6e Extension/DataCollector/FormDataExtractorInterface.phpnu[PK!| ]@ Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.phpnu[PK!((G/ Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.phpnu[PK!#1126 Extension/DataCollector/DataCollectorExtension.phpnu[PK!%`-; Extension/DataCollector/FormDataExtractor.phpnu[PK!1 uu;M Extension/DataCollector/Type/DataCollectorTypeExtension.phpnu[PK!uUSW W >R Extension/DependencyInjection/DependencyInjectionExtension.phpnu[PK!(s //^ ClickableInterface.phpnu[PK!H a FormView.phpnu[PK! ͋   o Forms.phpnu[PK! 9292^ form_div_layout.html.twignu[PK![[ form_table_layout.html.twignu[PK!vq TwigRenderer.phpnu[PK!b3}} TwigRendererEngineInterface.phpnu[PK!Qkk TwigRendererInterface.phpnu[PK!<\ TwigRendererEngine.phpnu[PK],