/** * {@inheritdoc} */ public function resolveType(FormTypeInterface $type) { $typeExtensions = array(); foreach ($this->extensions as $extension) { /* @var FormExtensionInterface $extension */ $typeExtensions = array_merge($typeExtensions, $extension->getTypeExtensions($type->getName())); } $parent = $type->getParent() ? $this->getType($type->getParent()) : null; return new ResolvedFormType($type, $typeExtensions, $parent); }
/** * @inheritdoc */ 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, array(), $parentType); }
/** * Adds a type. * * @param FormTypeInterface $type The type * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * form extensions or type registration in the Dependency * Injection Container instead. */ public function addType(FormTypeInterface $type) { $parentType = $type->getParent(); $this->registry->addType($this->resolvedTypeFactory->createResolvedType($type, array(), $parentType ? $this->registry->getType($parentType) : null)); }
/** * 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())); } set_error_handler(array('Symfony\\Component\\Form\\Test\\DeprecationErrorHandler', 'handleBC')); $this->addType($this->resolvedTypeFactory->createResolvedType($type, $typeExtensions, $parentType ? $this->getType($parentType) : null)); restore_error_handler(); }
/** * Returns a form builder. * * @param string|FormTypeInterface $type The type of the form * @param string $name The name of the form * @param mixed $data The initial data * @param array $options The options * @param FormBuilder $parent The parent builder * * @return FormBuilder The form builder * * @throws FormException if any given option is not applicable to the given type */ public function createNamedBuilder($type, $name, $data = null, array $options = array(), FormBuilder $parent = null) { if (!array_key_exists('data', $options)) { $options['data'] = $data; } $builder = null; $types = array(); $defaultOptions = array(); $optionValues = array(); $passedOptions = $options; // Bottom-up determination of the type hierarchy // Start with the actual type and look for the parent type // The complete hierarchy is saved in $types, the first entry being // the root and the last entry being the leaf (the concrete type) while (null !== $type) { if ($type instanceof FormTypeInterface) { if ($type->getName() == $type->getParent($options)) { throw new FormException(sprintf('The form type name "%s" for class "%s" cannot be the same as the parent type.', $type->getName(), get_class($type))); } $this->addType($type); } elseif (is_string($type)) { $type = $this->getType($type); } else { throw new UnexpectedTypeException($type, 'string or Symfony\\Component\\Form\\FormTypeInterface'); } array_unshift($types, $type); // getParent() cannot see default options set by this type nor // default options set by parent types // As a result, the options always have to be checked for // existence with isset() before using them in this method. $type = $type->getParent($options); } // Top-down determination of the options and default options foreach ($types as $type) { // Merge the default options of all types to an array of default // options. Default options of children override default options // of parents. // Default options of ancestors are already visible in the $options // array passed to the following methods. $defaultOptions = array_replace($defaultOptions, $type->getDefaultOptions($options)); $optionValues = array_merge_recursive($optionValues, $type->getAllowedOptionValues($options)); foreach ($type->getExtensions() as $typeExtension) { $defaultOptions = array_replace($defaultOptions, $typeExtension->getDefaultOptions($options)); $optionValues = array_merge_recursive($optionValues, $typeExtension->getAllowedOptionValues($options)); } // In each turn, the options are replaced by the combination of // the currently known default options and the passed options. // It is important to merge with $passedOptions and not with // $options, otherwise default options of parents would override // default options of child types. $options = array_replace($defaultOptions, $passedOptions); } $type = end($types); $knownOptions = array_keys($defaultOptions); $diff = array_diff(self::$requiredOptions, $knownOptions); if (count($diff) > 0) { throw new TypeDefinitionException(sprintf('Type "%s" should support the option(s) "%s"', $type->getName(), implode('", "', $diff))); } $diff = array_diff(array_keys($passedOptions), $knownOptions); if (count($diff) > 1) { throw new CreationException(sprintf('The options "%s" do not exist. Known options are: "%s"', implode('", "', $diff), implode('", "', $knownOptions))); } if (count($diff) > 0) { throw new CreationException(sprintf('The option "%s" does not exist. Known options are: "%s"', current($diff), implode('", "', $knownOptions))); } foreach ($optionValues as $option => $allowedValues) { if (!in_array($options[$option], $allowedValues, true)) { throw new CreationException(sprintf('The option "%s" has the value "%s", but is expected to be one of "%s"', $option, $options[$option], implode('", "', $allowedValues))); } } for ($i = 0, $l = count($types); $i < $l && !$builder; ++$i) { $builder = $types[$i]->createBuilder($name, $this, $options); } if (!$builder) { throw new TypeDefinitionException(sprintf('Type "%s" or any of its parents should return a FormBuilder instance from createBuilder()', $type->getName())); } $builder->setTypes($types); $builder->setCurrentLoadingType($type->getName()); $builder->setParent($parent); foreach ($types as $type) { $type->buildForm($builder, $options); foreach ($type->getExtensions() as $typeExtension) { $typeExtension->buildForm($builder, $options); } } $builder->setCurrentLoadingType(null); return $builder; }
/** * Returns a form builder. * * @param string|FormTypeInterface $type The type of the form * @param string $name The name of the form * @param mixed $data The initial data * @param array $options The options * @param FormBuilder $parent The parent builder * * @return FormBuilder The form builder * * @throws FormException if any given option is not applicable to the given type */ public function createNamedBuilder($type, $name, $data = null, array $options = array(), FormBuilder $parent = null) { if (!array_key_exists('data', $options)) { $options['data'] = $data; } $builder = null; $types = array(); $optionValues = array(); $knownOptions = array(); $optionsResolver = new OptionsResolver(); // Bottom-up determination of the type hierarchy // Start with the actual type and look for the parent type // The complete hierarchy is saved in $types, the first entry being // the root and the last entry being the leaf (the concrete type) while (null !== $type) { if ($type instanceof FormTypeInterface) { if ($type->getName() == $type->getParent($options)) { throw new FormException(sprintf('The form type name "%s" for class "%s" cannot be the same as the parent type.', $type->getName(), get_class($type))); } $this->addType($type); } elseif (is_string($type)) { $type = $this->getType($type); } else { throw new UnexpectedTypeException($type, 'string or Symfony\\Component\\Form\\FormTypeInterface'); } array_unshift($types, $type); // getParent() cannot see default options set by this type nor // default options set by parent types // As a result, the options always have to be checked for // existence with isset() before using them in this method. $type = $type->getParent($options); } // Top-down determination of the default options foreach ($types as $type) { // Merge the default options of all types to an array of default // options. Default options of children override default options // of parents. $typeOptions = $type->getDefaultOptions(); $optionsResolver->setDefaults($typeOptions); $optionsResolver->addAllowedValues($type->getAllowedOptionValues()); $knownOptions = array_merge($knownOptions, array_keys($typeOptions)); foreach ($type->getExtensions() as $typeExtension) { $extensionOptions = $typeExtension->getDefaultOptions(); $optionsResolver->setDefaults($extensionOptions); $optionsResolver->addAllowedValues($typeExtension->getAllowedOptionValues()); $knownOptions = array_merge($knownOptions, array_keys($extensionOptions)); } } // Resolve concrete type $type = end($types); // Validate options required by the factory $diff = array_diff(self::$requiredOptions, $knownOptions); if (count($diff) > 0) { throw new TypeDefinitionException(sprintf('Type "%s" should support the option(s) "%s"', $type->getName(), implode('", "', $diff))); } // Resolve options $options = $optionsResolver->resolve($options); for ($i = 0, $l = count($types); $i < $l && !$builder; ++$i) { $builder = $types[$i]->createBuilder($name, $this, $options); } if (!$builder) { throw new TypeDefinitionException(sprintf('Type "%s" or any of its parents should return a FormBuilder instance from createBuilder()', $type->getName())); } $builder->setTypes($types); $builder->setCurrentLoadingType($type->getName()); $builder->setParent($parent); foreach ($types as $type) { $type->buildForm($builder, $options); foreach ($type->getExtensions() as $typeExtension) { $typeExtension->buildForm($builder, $options); } } $builder->setCurrentLoadingType(null); return $builder; }
/** * 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) { $typeExtensions = array(); $parentType = $type->getParent(); $fqcn = get_class($type); foreach ($this->extensions as $extension) { $typeExtensions = array_merge($typeExtensions, $extension->getTypeExtensions($fqcn)); } return $this->resolvedTypeFactory->createResolvedType($type, $typeExtensions, $parentType ? $this->getType($parentType) : null); }
/** * 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) { $typeExtensions = array(); $parentType = $type->getParent(); $fqcn = get_class($type); $name = $type->getName(); $hasCustomName = $name !== $fqcn; if ($parentType instanceof FormTypeInterface) { @trigger_error('Returning a FormTypeInterface from FormTypeInterface::getParent() is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED); $this->resolveAndAddType($parentType); $parentType = $parentType->getName(); } if ($hasCustomName) { foreach ($this->extensions as $extension) { $typeExtensions = array_merge($typeExtensions, $extension->getTypeExtensions($name)); } if ($typeExtensions) { @trigger_error('Returning a type name from FormTypeExtensionInterface::getExtendedType() is deprecated since version 2.8 and will be removed in 3.0. Return the fully-qualified type class name instead.', E_USER_DEPRECATED); } } foreach ($this->extensions as $extension) { $typeExtensions = array_merge($typeExtensions, $extension->getTypeExtensions($fqcn)); } $resolvedType = $this->resolvedTypeFactory->createResolvedType($type, $typeExtensions, $parentType ? $this->getType($parentType) : null); $this->types[$fqcn] = $resolvedType; if ($hasCustomName) { // Enable access by the explicit type name until Symfony 3.0 $this->types[$name] = $resolvedType; $this->legacyNames[$name] = true; } }
/** * Returns a form builder. * * @param string|FormTypeInterface $type The type of the form * @param string $name The name of the form * @param mixed $data The initial data * @param array $options The options * * @return FormBuilder The form builder * * @throws FormException if any given option is not applicable to the given type */ public function createNamedBuilder($type, $name, $data = null, array $options = array()) { $builder = null; $types = array(); $knownOptions = array(); $passedOptions = array_keys($options); $optionValues = array(); if (!array_key_exists('data', $options)) { $options['data'] = $data; } while (null !== $type) { if ($type instanceof FormTypeInterface) { if ($type->getName() == $type->getParent($options)) { throw new FormException(sprintf('The form type name "%s" for class "%s" cannot be the same as the parent type.', $type->getName(), get_class($type))); } $this->addType($type); } elseif (is_string($type)) { $type = $this->getType($type); } else { throw new UnexpectedTypeException($type, 'string or Symfony\\Component\\Form\\FormTypeInterface'); } $defaultOptions = $type->getDefaultOptions($options); $optionValues = array_merge_recursive($optionValues, $type->getAllowedOptionValues($options)); foreach ($type->getExtensions() as $typeExtension) { $defaultOptions = array_replace($defaultOptions, $typeExtension->getDefaultOptions($options)); $optionValues = array_merge_recursive($optionValues, $typeExtension->getAllowedOptionValues($options)); } $options = array_replace($defaultOptions, $options); $knownOptions = array_merge($knownOptions, array_keys($defaultOptions)); array_unshift($types, $type); $type = $type->getParent($options); } $type = end($types); $diff = array_diff(self::$requiredOptions, $knownOptions); if (count($diff) > 0) { throw new TypeDefinitionException(sprintf('Type "%s" should support the option(s) "%s"', $type->getName(), implode('", "', $diff))); } $diff = array_diff($passedOptions, $knownOptions); if (count($diff) > 1) { throw new CreationException(sprintf('The options "%s" do not exist. Known options are: "%s"', implode('", "', $diff), implode('", "', $knownOptions))); } if (count($diff) > 0) { throw new CreationException(sprintf('The option "%s" does not exist. Known options are: "%s"', current($diff), implode('", "', $knownOptions))); } foreach ($optionValues as $option => $allowedValues) { if (!in_array($options[$option], $allowedValues, true)) { throw new CreationException(sprintf('The option "%s" has the value "%s", but is expected to be one of "%s"', $option, $options[$option], implode('", "', $allowedValues))); } } for ($i = 0, $l = count($types); $i < $l && !$builder; ++$i) { $builder = $types[$i]->createBuilder($name, $this, $options); } if (!$builder) { throw new TypeDefinitionException(sprintf('Type "%s" or any of its parents should return a FormBuilder instance from createBuilder()', $type->getName())); } $builder->setTypes($types); $builder->setCurrentLoadingType($type->getName()); foreach ($types as $type) { $type->buildForm($builder, $options); foreach ($type->getExtensions() as $typeExtension) { $typeExtension->buildForm($builder, $options); } } $builder->setCurrentLoadingType(null); return $builder; }
/** * 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 ); }
/** * 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) { $typeExtensions = array_merge($typeExtensions, $extension->getTypeExtensions($type->getName())); } $this->types[$type->getName()] = $this->resolvedTypeFactory->createResolvedType($type, $typeExtensions, $parentType ? $this->getType($parentType) : null); }