mirror of
https://github.com/wallabag/wallabag.git
synced 2025-09-05 18:41:02 +00:00
twig implementation
This commit is contained in:
parent
2b840e0cfb
commit
4f5b44bd3b
1418 changed files with 108207 additions and 1586 deletions
4
vendor/symfony/form/Symfony/Component/Form/.gitignore
vendored
Normal file
4
vendor/symfony/form/Symfony/Component/Form/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
vendor/
|
||||
composer.lock
|
||||
phpunit.xml
|
||||
|
195
vendor/symfony/form/Symfony/Component/Form/AbstractExtension.php
vendored
Normal file
195
vendor/symfony/form/Symfony/Component/Form/AbstractExtension.php
vendored
Normal file
|
@ -0,0 +1,195 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\Form\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
206
vendor/symfony/form/Symfony/Component/Form/AbstractRendererEngine.php
vendored
Normal file
206
vendor/symfony/form/Symfony/Component/Form/AbstractRendererEngine.php
vendored
Normal file
|
@ -0,0 +1,206 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link FormRendererEngineInterface}.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
56
vendor/symfony/form/Symfony/Component/Form/AbstractType.php
vendored
Normal file
56
vendor/symfony/form/Symfony/Component/Form/AbstractType.php
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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';
|
||||
}
|
||||
}
|
48
vendor/symfony/form/Symfony/Component/Form/AbstractTypeExtension.php
vendored
Normal file
48
vendor/symfony/form/Symfony/Component/Form/AbstractTypeExtension.php
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
436
vendor/symfony/form/Symfony/Component/Form/Button.php
vendored
Normal file
436
vendor/symfony/form/Symfony/Component/Form/Button.php
vendored
Normal file
|
@ -0,0 +1,436 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\Form\Exception\AlreadySubmittedException;
|
||||
use Symfony\Component\Form\Exception\BadMethodCallException;
|
||||
|
||||
/**
|
||||
* A form button.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class Button implements \IteratorAggregate, FormInterface
|
||||
{
|
||||
/**
|
||||
* @var FormInterface
|
||||
*/
|
||||
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)
|
||||
{
|
||||
throw new BadMethodCallException('Buttons cannot have data.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
return $this->config->getType()->createView($this, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
864
vendor/symfony/form/Symfony/Component/Form/ButtonBuilder.php
vendored
Normal file
864
vendor/symfony/form/Symfony/Component/Form/ButtonBuilder.php
vendored
Normal file
|
@ -0,0 +1,864 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/ButtonTypeInterface.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/ButtonTypeInterface.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
/**
|
||||
* A type that should be converted into a {@link Button} instance.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface ButtonTypeInterface extends FormTypeInterface
|
||||
{
|
||||
}
|
238
vendor/symfony/form/Symfony/Component/Form/CHANGELOG.md
vendored
Normal file
238
vendor/symfony/form/Symfony/Component/Form/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,238 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
|
||||
2.3.0
|
||||
------
|
||||
|
||||
* deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace
|
||||
* deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace
|
||||
* changed FormRenderer::humanize() to humanize also camel cased field name
|
||||
* added RequestHandlerInterface and FormInterface::handleRequest()
|
||||
* deprecated passing a Request instance to FormInterface::bind()
|
||||
* added options "method" and "action" to FormType
|
||||
* deprecated option "virtual" in favor "inherit_data"
|
||||
* deprecated VirtualFormAwareIterator in favor of InheritDataAwareIterator
|
||||
* [BC BREAK] removed the "array" type hint from DataMapperInterface
|
||||
* improved forms inheriting their parent data to actually return that data from getData(), getNormData() and getViewData()
|
||||
* added component-level exceptions for various SPL exceptions
|
||||
changed all uses of the deprecated Exception class to use more specialized exceptions instead
|
||||
removed NotInitializedException, NotValidException, TypeDefinitionException, TypeLoaderException, CreationException
|
||||
* added events PRE_SUBMIT, SUBMIT and POST_SUBMIT
|
||||
* deprecated events PRE_BIND, BIND and POST_BIND
|
||||
* [BC BREAK] renamed bind() and isBound() in FormInterface to submit() and isSubmitted()
|
||||
* added methods submit() and isSubmitted() to Form
|
||||
* deprecated bind() and isBound() in Form
|
||||
* deprecated AlreadyBoundException in favor of AlreadySubmittedException
|
||||
* added support for PATCH requests
|
||||
* [BC BREAK] added initialize() to FormInterface
|
||||
* [BC BREAK] added getAutoInitialize() to FormConfigInterface
|
||||
* [BC BREAK] added setAutoInitialize() to FormConfigBuilderInterface
|
||||
* [BC BREAK] initialization for Form instances added to a form tree must be manually disabled
|
||||
* PRE_SET_DATA is now guaranteed to be called after children were added by the form builder,
|
||||
unless FormInterface::setData() is called manually
|
||||
* fixed CSRF error message to be translated
|
||||
* custom CSRF error messages can now be set through the "csrf_message" option
|
||||
* fixed: expanded single-choice fields now show a radio button for the empty value
|
||||
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* TrimListener now removes unicode whitespaces
|
||||
* deprecated getParent(), setParent() and hasParent() in FormBuilderInterface
|
||||
* FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options
|
||||
* removed special characters between the choice or text fields of DateType unless
|
||||
the option "format" is set to a custom value
|
||||
* deprecated FormException and introduced ExceptionInterface instead
|
||||
* [BC BREAK] FormException is now an interface
|
||||
* protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig()
|
||||
* [BC BREAK] inserted argument `$message` in the constructor of `FormError`
|
||||
* the PropertyPath class and related classes were moved to a dedicated
|
||||
PropertyAccess component. During the move, InvalidPropertyException was
|
||||
renamed to NoSuchPropertyException. FormUtil was split: FormUtil::singularify()
|
||||
can now be found in Symfony\Component\PropertyAccess\StringUtil. The methods
|
||||
getValue() and setValue() from PropertyPath were extracted into a new class
|
||||
PropertyAccessor.
|
||||
* added an optional PropertyAccessorInterface parameter to FormType,
|
||||
ObjectChoiceList and PropertyPathMapper
|
||||
* [BC BREAK] PropertyPathMapper and FormType now have a constructor
|
||||
* [BC BREAK] setting the option "validation_groups" to ``false`` now disables validation
|
||||
instead of assuming group "Default"
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* [BC BREAK] ``read_only`` field attribute now renders as ``readonly="readonly"``, use ``disabled`` instead
|
||||
* [BC BREAK] child forms now aren't validated anymore by default
|
||||
* made validation of form children configurable (new option: cascade_validation)
|
||||
* added support for validation groups as callbacks
|
||||
* made the translation catalogue configurable via the "translation_domain" option
|
||||
* added Form::getErrorsAsString() to help debugging forms
|
||||
* allowed setting different options for RepeatedType fields (like the label)
|
||||
* added support for empty form name at root level, this enables rendering forms
|
||||
without form name prefix in field names
|
||||
* [BC BREAK] form and field names must start with a letter, digit or underscore
|
||||
and only contain letters, digits, underscores, hyphens and colons
|
||||
* [BC BREAK] changed default name of the prototype in the "collection" type
|
||||
from "$$name$$" to "\__name\__". No dollars are appended/prepended to custom
|
||||
names anymore.
|
||||
* [BC BREAK] improved ChoiceListInterface
|
||||
* [BC BREAK] added SimpleChoiceList and LazyChoiceList as replacement of
|
||||
ArrayChoiceList
|
||||
* added ChoiceList and ObjectChoiceList to use objects as choices
|
||||
* [BC BREAK] removed EntitiesToArrayTransformer and EntityToIdTransformer.
|
||||
The former has been replaced by CollectionToArrayTransformer in combination
|
||||
with EntityChoiceList, the latter is not required in the core anymore.
|
||||
* [BC BREAK] renamed
|
||||
* ArrayToBooleanChoicesTransformer to ChoicesToBooleanArrayTransformer
|
||||
* ScalarToBooleanChoicesTransformer to ChoiceToBooleanArrayTransformer
|
||||
* ArrayToChoicesTransformer to ChoicesToValuesTransformer
|
||||
* ScalarToChoiceTransformer to ChoiceToValueTransformer
|
||||
to be consistent with the naming in ChoiceListInterface.
|
||||
They were merged into ChoiceList and have no public equivalent anymore.
|
||||
* choice fields now throw a FormException if neither the "choices" nor the
|
||||
"choice_list" option is set
|
||||
* the radio type is now a child of the checkbox type
|
||||
* the collection, choice (with multiple selection) and entity (with multiple
|
||||
selection) types now make use of addXxx() and removeXxx() methods in your
|
||||
model if you set "by_reference" to false. For a custom, non-recognized
|
||||
singular form, set the "property_path" option like this: "plural|singular"
|
||||
* forms now don't create an empty object anymore if they are completely
|
||||
empty and not required. The empty value for such forms is null.
|
||||
* added constant Guess::VERY_HIGH_CONFIDENCE
|
||||
* [BC BREAK] The methods `add`, `remove`, `setParent`, `bind` and `setData`
|
||||
in class Form now throw an exception if the form is already bound
|
||||
* fields of constrained classes without a NotBlank or NotNull constraint are
|
||||
set to not required now, as stated in the docs
|
||||
* fixed TimeType and DateTimeType to not display seconds when "widget" is
|
||||
"single_text" unless "with_seconds" is set to true
|
||||
* checkboxes of in an expanded multiple-choice field don't include the choice
|
||||
in their name anymore. Their names terminate with "[]" now.
|
||||
* deprecated FormValidatorInterface and substituted its implementations
|
||||
by event subscribers
|
||||
* simplified CSRF protection and removed the csrf type
|
||||
* deprecated FieldType and merged it into FormType
|
||||
* added new option "compound" that lets you switch between field and form behavior
|
||||
* [BC BREAK] renamed theme blocks
|
||||
* "field_*" to "form_*"
|
||||
* "field_widget" to "form_widget_simple"
|
||||
* "widget_choice_options" to "choice_widget_options"
|
||||
* "generic_label" to "form_label"
|
||||
* added theme blocks "form_widget_compound", "choice_widget_expanded" and
|
||||
"choice_widget_collapsed" to make theming more modular
|
||||
* ValidatorTypeGuesser now guesses "collection" for array type constraint
|
||||
* added method `guessPattern` to FormTypeGuesserInterface to guess which pattern to use in the HTML5 attribute "pattern"
|
||||
* deprecated method `guessMinLength` in favor of `guessPattern`
|
||||
* labels don't display field attributes anymore. Label attributes can be
|
||||
passed in the "label_attr" option/variable
|
||||
* added option "mapped" which should be used instead of setting "property_path" to false
|
||||
* [BC BREAK] "data_class" now *must* be set if a form maps to an object and should be left empty otherwise
|
||||
* improved error mapping on forms
|
||||
* dot (".") rules are now allowed to map errors assigned to a form to
|
||||
one of its children
|
||||
* errors are not mapped to unsynchronized forms anymore
|
||||
* [BC BREAK] changed Form constructor to accept a single `FormConfigInterface` object
|
||||
* [BC BREAK] changed argument order in the FormBuilder constructor
|
||||
* added Form method `getViewData`
|
||||
* deprecated Form methods
|
||||
* `getTypes`
|
||||
* `getErrorBubbling`
|
||||
* `getNormTransformers`
|
||||
* `getClientTransformers`
|
||||
* `getAttribute`
|
||||
* `hasAttribute`
|
||||
* `getClientData`
|
||||
* added FormBuilder methods
|
||||
* `getTypes`
|
||||
* `addViewTransformer`
|
||||
* `getViewTransformers`
|
||||
* `resetViewTransformers`
|
||||
* `addModelTransformer`
|
||||
* `getModelTransformers`
|
||||
* `resetModelTransformers`
|
||||
* deprecated FormBuilder methods
|
||||
* `prependClientTransformer`
|
||||
* `appendClientTransformer`
|
||||
* `getClientTransformers`
|
||||
* `resetClientTransformers`
|
||||
* `prependNormTransformer`
|
||||
* `appendNormTransformer`
|
||||
* `getNormTransformers`
|
||||
* `resetNormTransformers`
|
||||
* deprecated the option "validation_constraint" in favor of the new
|
||||
option "constraints"
|
||||
* removed superfluous methods from DataMapperInterface
|
||||
* `mapFormToData`
|
||||
* `mapDataToForm`
|
||||
* added `setDefaultOptions` to FormTypeInterface and FormTypeExtensionInterface
|
||||
which accepts an OptionsResolverInterface instance
|
||||
* deprecated the methods `getDefaultOptions` and `getAllowedOptionValues`
|
||||
in FormTypeInterface and FormTypeExtensionInterface
|
||||
* options passed during construction can now be accessed from FormConfigInterface
|
||||
* added FormBuilderInterface and FormConfigEditorInterface
|
||||
* [BC BREAK] the method `buildForm` in FormTypeInterface and FormTypeExtensionInterface
|
||||
now receives a FormBuilderInterface instead of a FormBuilder instance
|
||||
* [BC BREAK] the method `buildViewBottomUp` was renamed to `finishView` in
|
||||
FormTypeInterface and FormTypeExtensionInterface
|
||||
* [BC BREAK] the options array is now passed as last argument of the
|
||||
methods
|
||||
* `buildView`
|
||||
* `finishView`
|
||||
in FormTypeInterface and FormTypeExtensionInterface
|
||||
* [BC BREAK] no options are passed to `getParent` of FormTypeInterface anymore
|
||||
* deprecated DataEvent and FilterDataEvent in favor of the new FormEvent which is
|
||||
now passed to all events thrown by the component
|
||||
* FormEvents::BIND now replaces FormEvents::BIND_NORM_DATA
|
||||
* FormEvents::PRE_SET_DATA now replaces FormEvents::SET_DATA
|
||||
* FormEvents::PRE_BIND now replaces FormEvents::BIND_CLIENT_DATA
|
||||
* deprecated FormEvents::SET_DATA, FormEvents::BIND_CLIENT_DATA and
|
||||
FormEvents::BIND_NORM_DATA
|
||||
* [BC BREAK] reversed the order of the first two arguments to `createNamed`
|
||||
and `createNamedBuilder` in `FormFactoryInterface`
|
||||
* deprecated `getChildren` in Form and FormBuilder in favor of `all`
|
||||
* deprecated `hasChildren` in Form and FormBuilder in favor of `count`
|
||||
* FormBuilder now implements \IteratorAggregate
|
||||
* [BC BREAK] compound forms now always need a data mapper
|
||||
* FormBuilder now maintains the order when explicitly adding form builders as children
|
||||
* ChoiceType now doesn't add the empty value anymore if the choices already contain an empty element
|
||||
* DateType, TimeType and DateTimeType now show empty values again if not required
|
||||
* [BC BREAK] fixed rendering of errors for DateType, BirthdayType and similar ones
|
||||
* [BC BREAK] fixed: form constraints are only validated if they belong to the validated group
|
||||
* deprecated `bindRequest` in `Form` and replaced it by a listener to FormEvents::PRE_BIND
|
||||
* fixed: the "data" option supersedes default values from the model
|
||||
* changed DateType to refer to the "format" option for calculating the year and day choices instead
|
||||
of padding them automatically
|
||||
* [BC BREAK] DateType defaults to the format "yyyy-MM-dd" now if the widget is
|
||||
"single_text", in order to support the HTML 5 date field out of the box
|
||||
* added the option "format" to DateTimeType
|
||||
* [BC BREAK] DateTimeType now outputs RFC 3339 dates by default, as generated and
|
||||
consumed by HTML5 browsers, if the widget is "single_text"
|
||||
* deprecated the options "data_timezone" and "user_timezone" in DateType, DateTimeType and TimeType
|
||||
and renamed them to "model_timezone" and "view_timezone"
|
||||
* fixed: TransformationFailedExceptions thrown in the model transformer are now caught by the form
|
||||
* added FormRegistryInterface, ResolvedFormTypeInterface and ResolvedFormTypeFactoryInterface
|
||||
* deprecated FormFactory methods
|
||||
* `addType`
|
||||
* `hasType`
|
||||
* `getType`
|
||||
* [BC BREAK] FormFactory now expects a FormRegistryInterface and a ResolvedFormTypeFactoryInterface as constructor argument
|
||||
* [BC BREAK] The method `createBuilder` in FormTypeInterface is not supported anymore for performance reasons
|
||||
* [BC BREAK] Removed `setTypes` from FormBuilder
|
||||
* deprecated AbstractType methods
|
||||
* `getExtensions`
|
||||
* `setExtensions`
|
||||
* ChoiceType now caches its created choice lists to improve performance
|
||||
* [BC BREAK] Rows of a collection field cannot be themed individually anymore. All rows in the collection
|
||||
field now have the same block names, which contains "entry" where it previously contained the row index.
|
||||
* [BC BREAK] When registering a type through the DI extension, the tag alias has to match the actual type name.
|
||||
* added FormRendererInterface, FormRendererEngineInterface and implementations of these interfaces
|
||||
* [BC BREAK] removed the following methods from FormUtil:
|
||||
* `toArrayKey`
|
||||
* `toArrayKeys`
|
||||
* `isChoiceGroup`
|
||||
* `isChoiceSelected`
|
||||
* [BC BREAK] renamed method `renderBlock` in FormHelper to `block` and changed its signature
|
||||
* made FormView properties public and deprecated their accessor methods
|
||||
* made the normalized data of a form accessible in the template through the variable "form.vars.data"
|
||||
* made the original data of a choice accessible in the template through the property "choice.data"
|
||||
* added convenience class Forms and FormFactoryBuilderInterface
|
70
vendor/symfony/form/Symfony/Component/Form/CallbackTransformer.php
vendored
Normal file
70
vendor/symfony/form/Symfony/Component/Form/CallbackTransformer.php
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
27
vendor/symfony/form/Symfony/Component/Form/ClickableInterface.php
vendored
Normal file
27
vendor/symfony/form/Symfony/Component/Form/ClickableInterface.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
/**
|
||||
* A clickable form element.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface ClickableInterface
|
||||
{
|
||||
/**
|
||||
* Returns whether this element was clicked.
|
||||
*
|
||||
* @return Boolean Whether this element was clicked.
|
||||
*/
|
||||
public function isClicked();
|
||||
}
|
38
vendor/symfony/form/Symfony/Component/Form/DataMapperInterface.php
vendored
Normal file
38
vendor/symfony/form/Symfony/Component/Form/DataMapperInterface.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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);
|
||||
}
|
77
vendor/symfony/form/Symfony/Component/Form/DataTransformerInterface.php
vendored
Normal file
77
vendor/symfony/form/Symfony/Component/Form/DataTransformerInterface.php
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* Transforms a value between different representations.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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);
|
||||
}
|
22
vendor/symfony/form/Symfony/Component/Form/Exception/AlreadyBoundException.php
vendored
Normal file
22
vendor/symfony/form/Symfony/Component/Form/Exception/AlreadyBoundException.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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
|
||||
{
|
||||
}
|
22
vendor/symfony/form/Symfony/Component/Form/Exception/AlreadySubmittedException.php
vendored
Normal file
22
vendor/symfony/form/Symfony/Component/Form/Exception/AlreadySubmittedException.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when an operation is called that is not acceptable after submitting
|
||||
* a form.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class AlreadySubmittedException extends AlreadyBoundException
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/BadMethodCallException.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/BadMethodCallException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Base BadMethodCallException for the Form component.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
|
||||
{
|
||||
}
|
16
vendor/symfony/form/Symfony/Component/Form/Exception/ErrorMappingException.php
vendored
Normal file
16
vendor/symfony/form/Symfony/Component/Form/Exception/ErrorMappingException.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
class ErrorMappingException extends RuntimeException
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/ExceptionInterface.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/ExceptionInterface.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Base ExceptionInterface for the Form component.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/InvalidArgumentException.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/InvalidArgumentException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Base InvalidArgumentException for the Form component.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
16
vendor/symfony/form/Symfony/Component/Form/Exception/InvalidConfigurationException.php
vendored
Normal file
16
vendor/symfony/form/Symfony/Component/Form/Exception/InvalidConfigurationException.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
class InvalidConfigurationException extends InvalidArgumentException
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/LogicException.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/LogicException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Base LogicException for Form component.
|
||||
*
|
||||
* @author Alexander Kotynia <aleksander.kot@gmail.com>
|
||||
*/
|
||||
class LogicException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/OutOfBoundsException.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/OutOfBoundsException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Base OutOfBoundsException for Form component.
|
||||
*
|
||||
* @author Alexander Kotynia <aleksander.kot@gmail.com>
|
||||
*/
|
||||
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/RuntimeException.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/RuntimeException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Base RuntimeException for the Form component.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
16
vendor/symfony/form/Symfony/Component/Form/Exception/StringCastException.php
vendored
Normal file
16
vendor/symfony/form/Symfony/Component/Form/Exception/StringCastException.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
class StringCastException extends RuntimeException
|
||||
{
|
||||
}
|
21
vendor/symfony/form/Symfony/Component/Form/Exception/TransformationFailedException.php
vendored
Normal file
21
vendor/symfony/form/Symfony/Component/Form/Exception/TransformationFailedException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Exception;
|
||||
|
||||
/**
|
||||
* Indicates a value transformation error.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class TransformationFailedException extends RuntimeException
|
||||
{
|
||||
}
|
20
vendor/symfony/form/Symfony/Component/Form/Exception/UnexpectedTypeException.php
vendored
Normal file
20
vendor/symfony/form/Symfony/Component/Form/Exception/UnexpectedTypeException.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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)));
|
||||
}
|
||||
}
|
510
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php
vendored
Normal file
510
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php
vendored
Normal file
|
@ -0,0 +1,510 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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.
|
||||
*
|
||||
* <code>
|
||||
* $choices = array(true, false);
|
||||
* $labels = array('Agree', 'Disagree');
|
||||
* $choiceList = new ChoiceList($choices, $labels);
|
||||
* </code>
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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 $j => $givenValue) {
|
||||
foreach ($this->values as $i => $value) {
|
||||
if ($value === $givenValue) {
|
||||
$choices[] = $this->choices[$i];
|
||||
unset($values[$j]);
|
||||
|
||||
if (0 === count($values)) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValuesForChoices(array $choices)
|
||||
{
|
||||
$choices = $this->fixChoices($choices);
|
||||
$values = array();
|
||||
|
||||
foreach ($this->choices as $i => $choice) {
|
||||
foreach ($choices as $j => $givenChoice) {
|
||||
if ($choice === $givenChoice) {
|
||||
$values[] = $this->values[$i];
|
||||
unset($choices[$j]);
|
||||
|
||||
if (0 === count($choices)) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIndicesForChoices(array $choices)
|
||||
{
|
||||
$choices = $this->fixChoices($choices);
|
||||
$indices = array();
|
||||
|
||||
foreach ($this->choices as $i => $choice) {
|
||||
foreach ($choices as $j => $givenChoice) {
|
||||
if ($choice === $givenChoice) {
|
||||
$indices[] = $i;
|
||||
unset($choices[$j]);
|
||||
|
||||
if (0 === count($choices)) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $indices;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIndicesForValues(array $values)
|
||||
{
|
||||
$values = $this->fixValues($values);
|
||||
$indices = array();
|
||||
|
||||
foreach ($this->values as $i => $value) {
|
||||
foreach ($values as $j => $givenValue) {
|
||||
if ($value === $givenValue) {
|
||||
$indices[] = $i;
|
||||
unset($values[$j]);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
149
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php
vendored
Normal file
149
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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:
|
||||
*
|
||||
* <source>
|
||||
* array(
|
||||
* 'Group 1' => array(
|
||||
* 10 => ChoiceView object,
|
||||
* 20 => ChoiceView object,
|
||||
* ),
|
||||
* 'Group 2' => array(
|
||||
* 30 => ChoiceView object,
|
||||
* ),
|
||||
* )
|
||||
* </source>
|
||||
*
|
||||
* @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:
|
||||
*
|
||||
* <source>
|
||||
* array(
|
||||
* 'Group 1' => array(
|
||||
* 10 => ChoiceView object,
|
||||
* 20 => ChoiceView object,
|
||||
* ),
|
||||
* 'Group 2' => array(
|
||||
* 30 => ChoiceView object,
|
||||
* ),
|
||||
* )
|
||||
* </source>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public function getIndicesForValues(array $values);
|
||||
}
|
149
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php
vendored
Normal file
149
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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}
|
||||
*/
|
||||
public function getIndicesForChoices(array $choices)
|
||||
{
|
||||
if (!$this->choiceList) {
|
||||
$this->load();
|
||||
}
|
||||
|
||||
return $this->choiceList->getIndicesForChoices($choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
184
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php
vendored
Normal file
184
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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).
|
||||
*
|
||||
* <code>
|
||||
* $choices = array($user1, $user2);
|
||||
*
|
||||
* // call getName() to determine the choice labels
|
||||
* $choiceList = new ObjectChoiceList($choices, 'name');
|
||||
* </code>
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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::getPropertyAccessor();
|
||||
$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 {
|
||||
if (!isset($groupedChoices[$group])) {
|
||||
$groupedChoices[$group] = array();
|
||||
}
|
||||
|
||||
$groupedChoices[$group][$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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
164
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php
vendored
Normal file
164
vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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.
|
||||
*
|
||||
* <code>
|
||||
* $choiceList = new SimpleChoiceList(array(
|
||||
* 'creditcard' => 'Credit card payment',
|
||||
* 'cash' => 'Cash payment',
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
59
vendor/symfony/form/Symfony/Component/Form/Extension/Core/CoreExtension.php
vendored
Normal file
59
vendor/symfony/form/Symfony/Component/Form/Extension/Core/CoreExtension.php
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
class CoreExtension extends AbstractExtension
|
||||
{
|
||||
protected function loadTypes()
|
||||
{
|
||||
return array(
|
||||
new Type\FormType(PropertyAccess::getPropertyAccessor()),
|
||||
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(),
|
||||
);
|
||||
}
|
||||
}
|
92
vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php
vendored
Normal file
92
vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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::getPropertyAccessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mapDataToForms($data, $forms)
|
||||
{
|
||||
if (null === $data || array() === $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();
|
||||
|
||||
if (null !== $propertyPath && $config->getMapped()) {
|
||||
$form->setData($this->propertyAccessor->getValue($data, $propertyPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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)
|
||||
// and if the form is disabled (modification not allowed)
|
||||
if (null !== $propertyPath && $config->getMapped() && $form->isSynchronized() && !$form->isDisabled()) {
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
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
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
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 true === $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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
$index = current($this->choiceList->getIndicesForChoices(array($choice)));
|
||||
|
||||
foreach ($values as $i => $value) {
|
||||
$values[$i] = $i === $index;
|
||||
}
|
||||
|
||||
if ($this->placeholderPresent) {
|
||||
$values['placeholder'] = false === $index;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
$indexMap = array_flip($this->choiceList->getIndicesForChoices($array));
|
||||
|
||||
foreach ($values as $i => $value) {
|
||||
$values[$i] = isset($indexMap[$i]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
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($value['month']) && !is_int($value['month'])) {
|
||||
throw new TransformationFailedException('This month is invalid');
|
||||
}
|
||||
|
||||
if (isset($value['day']) && !ctype_digit($value['day']) && !is_int($value['day'])) {
|
||||
throw new TransformationFailedException('This day is invalid');
|
||||
}
|
||||
|
||||
if (isset($value['year']) && !ctype_digit($value['year']) && !is_int($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');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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 !== $this->inputTimezone) {
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
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<day>[djDl])|' .
|
||||
'(?P<month>[FMmn])|' .
|
||||
'(?P<year>[Yy])|' .
|
||||
'(?P<hour>[ghGH])|' .
|
||||
'(?P<minute>i)|' .
|
||||
'(?P<second>s)|' .
|
||||
'(?P<dayofyear>z)|' .
|
||||
'(?P<timestamp>U)|' .
|
||||
'[^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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* Transforms between a timestamp and a DateTime object
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* Transforms between an integer and a localized number with grouping
|
||||
* (each thousand) and comma separators.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
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 integer');
|
||||
}
|
||||
|
||||
$formatter = $this->getNumberFormatter();
|
||||
$value = $formatter->parse(
|
||||
$value,
|
||||
PHP_INT_SIZE == 8 ? $formatter::TYPE_INT64 : $formatter::TYPE_INT32
|
||||
);
|
||||
|
||||
if (intl_is_failure($formatter->getErrorCode())) {
|
||||
throw new TransformationFailedException($formatter->getErrorMessage());
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
|
||||
{
|
||||
|
||||
private $divisor;
|
||||
|
||||
public function __construct($precision = null, $grouping = null, $roundingMode = null, $divisor = null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
class NumberToLocalizedStringTransformer implements DataTransformerInterface
|
||||
{
|
||||
const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR;
|
||||
const ROUND_DOWN = \NumberFormatter::ROUND_DOWN;
|
||||
const ROUND_HALFDOWN = \NumberFormatter::ROUND_HALFDOWN;
|
||||
const ROUND_HALFEVEN = \NumberFormatter::ROUND_HALFEVEN;
|
||||
const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP;
|
||||
const ROUND_UP = \NumberFormatter::ROUND_UP;
|
||||
const ROUND_CEILING = \NumberFormatter::ROUND_CEILING;
|
||||
|
||||
protected $precision;
|
||||
|
||||
protected $grouping;
|
||||
|
||||
protected $roundingMode;
|
||||
|
||||
public function __construct($precision = null, $grouping = null, $roundingMode = null)
|
||||
{
|
||||
if (null === $grouping) {
|
||||
$grouping = false;
|
||||
}
|
||||
|
||||
if (null === $roundingMode) {
|
||||
$roundingMode = self::ROUND_HALFUP;
|
||||
}
|
||||
|
||||
$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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
* @author Florian Eckerstorfer <florian@eckerstorfer.org>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 list of checkboxes to a correctly
|
||||
* indexed array.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class FixCheckboxInputListener implements EventSubscriberInterface
|
||||
{
|
||||
private $choiceList;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ChoiceListInterface $choiceList
|
||||
*/
|
||||
public function __construct(ChoiceListInterface $choiceList)
|
||||
{
|
||||
$this->choiceList = $choiceList;
|
||||
}
|
||||
|
||||
public function preSubmit(FormEvent $event)
|
||||
{
|
||||
$values = (array) $event->getData();
|
||||
$indices = $this->choiceList->getIndicesForValues($values);
|
||||
|
||||
$event->setData(count($indices) > 0 ? array_combine($indices, $values) : array());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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)
|
||||
{
|
||||
$value = $event->getData();
|
||||
$index = current($this->choiceList->getIndicesForValues(array($value)));
|
||||
|
||||
$event->setData(false !== $index ? array($index => $value) : ($this->placeholderPresent ? array('placeholder' => '') : array())) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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');
|
||||
}
|
||||
}
|
137
vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php
vendored
Normal file
137
vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
173
vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php
vendored
Normal file
173
vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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) {
|
||||
foreach ($data as $name => $child) {
|
||||
if (!$form->has($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);
|
||||
}
|
||||
}
|
55
vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php
vendored
Normal file
55
vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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');
|
||||
}
|
||||
}
|
121
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BaseType.php
vendored
Normal file
121
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BaseType.php
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
abstract class BaseType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->setDisabled($options['disabled']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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,
|
||||
));
|
||||
|
||||
$resolver->setAllowedTypes(array(
|
||||
'attr' => 'array',
|
||||
));
|
||||
}
|
||||
}
|
44
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php
vendored
Normal file
44
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
38
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ButtonType.php
vendored
Normal file
38
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ButtonType.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\Type;
|
||||
|
||||
use Symfony\Component\Form\ButtonTypeInterface;
|
||||
|
||||
/**
|
||||
* A form button.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ButtonType extends BaseType implements ButtonTypeInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'button';
|
||||
}
|
||||
}
|
67
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php
vendored
Normal file
67
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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)
|
||||
{
|
||||
$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, $clientData) {
|
||||
return $clientData;
|
||||
};
|
||||
|
||||
$resolver->setDefaults(array(
|
||||
'value' => '1',
|
||||
'empty_data' => $emptyData,
|
||||
'compound' => false,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'checkbox';
|
||||
}
|
||||
}
|
274
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php
vendored
Normal file
274
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php
vendored
Normal file
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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']->getIndicesForValues(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
|
||||
// Only add the empty value option if this is not the case
|
||||
if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) {
|
||||
$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 = md5(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
103
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CollectionType.php
vendored
Normal file
103
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CollectionType.php
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
45
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CountryType.php
vendored
Normal file
45
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CountryType.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
45
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php
vendored
Normal file
45
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
281
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php
vendored
Normal file
281
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php
vendored
Normal file
|
@ -0,0 +1,281 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
309
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateType.php
vendored
Normal file
309
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateType.php
vendored
Normal file
|
@ -0,0 +1,309 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||
$formatter->setTimeZone(\DateTimeZone::UTC);
|
||||
} else {
|
||||
$formatter->setTimeZoneId(\DateTimeZone::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 (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) {
|
||||
$formatter->setTimeZone($timezone);
|
||||
} else {
|
||||
$formatter->setTimeZoneId($timezone);
|
||||
}
|
||||
|
||||
return $timestamps;
|
||||
}
|
||||
|
||||
private function listYears(array $years)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
foreach ($years as $year) {
|
||||
$result[$year] = gmmktime(0, 0, 0, 6, 15, $year);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
33
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/EmailType.php
vendored
Normal file
33
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/EmailType.php
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
61
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FileType.php
vendored
Normal file
61
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FileType.php
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
214
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FormType.php
vendored
Normal file
214
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FormType.php
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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::getPropertyAccessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
parent::buildForm($builder, $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(isset($options['data']) ? $options['data'] : null)
|
||||
->setDataLocked(isset($options['data']))
|
||||
->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
|
||||
->setMethod($options['method'])
|
||||
->setAction($options['action'])
|
||||
->setAutoInitialize($options['auto_initialize'])
|
||||
;
|
||||
|
||||
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(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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' => '',
|
||||
'auto_initialize' => true,
|
||||
));
|
||||
|
||||
$resolver->setAllowedTypes(array(
|
||||
'label_attr' => 'array',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'form';
|
||||
}
|
||||
}
|
40
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/HiddenType.php
vendored
Normal file
40
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/HiddenType.php
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
68
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/IntegerType.php
vendored
Normal file
68
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/IntegerType.php
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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' => \NumberFormatter::ROUND_DOWN,
|
||||
'compound' => false,
|
||||
));
|
||||
|
||||
$resolver->setAllowedValues(array(
|
||||
'rounding_mode' => array(
|
||||
\NumberFormatter::ROUND_FLOOR,
|
||||
\NumberFormatter::ROUND_DOWN,
|
||||
\NumberFormatter::ROUND_HALFDOWN,
|
||||
\NumberFormatter::ROUND_HALFEVEN,
|
||||
\NumberFormatter::ROUND_HALFUP,
|
||||
\NumberFormatter::ROUND_UP,
|
||||
\NumberFormatter::ROUND_CEILING,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'integer';
|
||||
}
|
||||
}
|
45
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LanguageType.php
vendored
Normal file
45
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LanguageType.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
46
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LocaleType.php
vendored
Normal file
46
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LocaleType.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
111
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/MoneyType.php
vendored
Normal file
111
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/MoneyType.php
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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];
|
||||
}
|
||||
}
|
66
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/NumberType.php
vendored
Normal file
66
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/NumberType.php
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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' => \NumberFormatter::ROUND_HALFUP,
|
||||
'compound' => false,
|
||||
));
|
||||
|
||||
$resolver->setAllowedValues(array(
|
||||
'rounding_mode' => array(
|
||||
\NumberFormatter::ROUND_FLOOR,
|
||||
\NumberFormatter::ROUND_DOWN,
|
||||
\NumberFormatter::ROUND_HALFDOWN,
|
||||
\NumberFormatter::ROUND_HALFEVEN,
|
||||
\NumberFormatter::ROUND_HALFUP,
|
||||
\NumberFormatter::ROUND_UP,
|
||||
\NumberFormatter::ROUND_CEILING,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'number';
|
||||
}
|
||||
}
|
57
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PasswordType.php
vendored
Normal file
57
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PasswordType.php
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
55
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PercentType.php
vendored
Normal file
55
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PercentType.php
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
33
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RadioType.php
vendored
Normal file
33
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RadioType.php
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
67
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php
vendored
Normal file
67
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
39
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ResetType.php
vendored
Normal file
39
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ResetType.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\ButtonTypeInterface;
|
||||
|
||||
/**
|
||||
* A reset button.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class ResetType extends AbstractType implements ButtonTypeInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return 'button';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'reset';
|
||||
}
|
||||
}
|
33
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SearchType.php
vendored
Normal file
33
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SearchType.php
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
46
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SubmitType.php
vendored
Normal file
46
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SubmitType.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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';
|
||||
}
|
||||
}
|
36
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextType.php
vendored
Normal file
36
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextType.php
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
43
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextareaType.php
vendored
Normal file
43
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextareaType.php
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
225
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimeType.php
vendored
Normal file
225
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimeType.php
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
86
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php
vendored
Normal file
86
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
54
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/UrlType.php
vendored
Normal file
54
vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/UrlType.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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';
|
||||
}
|
||||
}
|
55
vendor/symfony/form/Symfony/Component/Form/Extension/Core/View/ChoiceView.php
vendored
Normal file
55
vendor/symfony/form/Symfony/Component/Form/Extension/Core/View/ChoiceView.php
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\View;
|
||||
|
||||
/**
|
||||
* Represents a choice in templates.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
64
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php
vendored
Normal file
64
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Csrf;
|
||||
|
||||
use Symfony\Component\Form\Extension\Csrf\Type;
|
||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||
use Symfony\Component\Form\AbstractExtension;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* This extension protects forms by using a CSRF token.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class CsrfExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* @var CsrfProviderInterface
|
||||
*/
|
||||
private $csrfProvider;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $translationDomain;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param CsrfProviderInterface $csrfProvider The CSRF provider
|
||||
* @param TranslatorInterface $translator The translator for translating error messages.
|
||||
* @param null|string $translationDomain The translation domain for translating.
|
||||
*/
|
||||
public function __construct(CsrfProviderInterface $csrfProvider, TranslatorInterface $translator = null, $translationDomain = null)
|
||||
{
|
||||
$this->csrfProvider = $csrfProvider;
|
||||
$this->translator = $translator;
|
||||
$this->translationDomain = $translationDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function loadTypeExtensions()
|
||||
{
|
||||
return array(
|
||||
new Type\FormTypeCsrfExtension($this->csrfProvider, true, '_token', $this->translator, $this->translationDomain),
|
||||
);
|
||||
}
|
||||
}
|
49
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php
vendored
Normal file
49
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
}
|
78
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php
vendored
Normal file
78
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
57
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php
vendored
Normal file
57
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
115
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
vendored
Normal file
115
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Csrf\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class CsrfValidationListener implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* The name of the CSRF field
|
||||
* @var string
|
||||
*/
|
||||
private $fieldName;
|
||||
|
||||
/**
|
||||
* The provider for generating and validating CSRF tokens
|
||||
* @var CsrfProviderInterface
|
||||
*/
|
||||
private $csrfProvider;
|
||||
|
||||
/**
|
||||
* A text mentioning the intention of the CSRF token
|
||||
*
|
||||
* Validation of the token will only succeed if it was generated in the
|
||||
* same session and with the same intention.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $intention;
|
||||
|
||||
/**
|
||||
* 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, CsrfProviderInterface $csrfProvider, $intention, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null)
|
||||
{
|
||||
$this->fieldName = $fieldName;
|
||||
$this->csrfProvider = $csrfProvider;
|
||||
$this->intention = $intention;
|
||||
$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->csrfProvider->isCsrfTokenValid($this->intention, $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);
|
||||
}
|
||||
}
|
129
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php
vendored
Normal file
129
vendor/symfony/form/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Csrf\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||
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\OptionsResolverInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class FormTypeCsrfExtension extends AbstractTypeExtension
|
||||
{
|
||||
/**
|
||||
* @var CsrfProviderInterface
|
||||
*/
|
||||
private $defaultCsrfProvider;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $defaultEnabled;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $defaultFieldName;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $translationDomain;
|
||||
|
||||
public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null)
|
||||
{
|
||||
$this->defaultCsrfProvider = $defaultCsrfProvider;
|
||||
$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
|
||||
->setAttribute('csrf_factory', $builder->getFormFactory())
|
||||
->addEventSubscriber(new CsrfValidationListener(
|
||||
$options['csrf_field_name'],
|
||||
$options['csrf_provider'],
|
||||
$options['intention'],
|
||||
$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()->getAttribute('csrf_factory');
|
||||
$data = $options['csrf_provider']->generateCsrfToken($options['intention']);
|
||||
|
||||
$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)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'csrf_protection' => $this->defaultEnabled,
|
||||
'csrf_field_name' => $this->defaultFieldName,
|
||||
'csrf_provider' => $this->defaultCsrfProvider,
|
||||
'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.',
|
||||
'intention' => 'unknown',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getExtendedType()
|
||||
{
|
||||
return 'form';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 $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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*
|
||||
* @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the
|
||||
* Request instance to {@link Form::process()} 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);
|
||||
}
|
||||
}
|
29
vendor/symfony/form/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.php
vendored
Normal file
29
vendor/symfony/form/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationExtension.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\HttpFoundation;
|
||||
|
||||
use Symfony\Component\Form\AbstractExtension;
|
||||
|
||||
/**
|
||||
* Integrates the HttpFoundation component with the Form library.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class HttpFoundationExtension extends AbstractExtension
|
||||
{
|
||||
protected function loadTypeExtensions()
|
||||
{
|
||||
return array(
|
||||
new Type\FormTypeHttpFoundationExtension(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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();
|
||||
} else {
|
||||
$default = $form->getConfig()->getCompound() ? array() : null;
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace 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 <bschussek@gmail.com>
|
||||
*/
|
||||
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';
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue