Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\DataTransformer;
use Sonata\CoreBundle\Form\Type\BooleanType;
use Symfony\Component\Form\DataTransformerInterface;
class BooleanTypeToBooleanTransformer implements DataTransformerInterface
{
/**
* {@inheritdoc}
*/
public function transform($value)
{
if ($value === true or (int) $value === BooleanType::TYPE_YES) {
return BooleanType::TYPE_YES;
}
return BooleanType::TYPE_NO;
}
/**
* {@inheritdoc}
*/
public function reverseTransform($value)
{
if ($value === BooleanType::TYPE_YES) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
/**
* Using BooleanToStringTransform in a checkbox form type
* will set false value to '0' instead of null which will end up
* returning true value when the form is bind.
*
* @author Sylvain Rascar <rascar.sylvain@gmail.com>
*/
class FixCheckboxDataListener implements EventSubscriberInterface
{
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
// NEXT_MAJOR: change `preBind` to `preSubmit`
return array(FormEvents::PRE_SUBMIT => 'preBind');
}
/**
* NEXT_MAJOR: remove this method.
*
* @param FormEvent $event
*
* @deprecated Since version 2.3, to be renamed in 4.0.
* Use {@link preSubmit} instead
*/
public function preBind(FormEvent $event)
{
// BC prevention for class extending this one.
if (get_called_class() !== 'Sonata\CoreBundle\Form\EventListener\FixCheckboxDataListener') {
@trigger_error(
__METHOD__.' is deprecated since 2.3 and will be renamed in 4.0.'
.' Use '.__CLASS__.'::preSubmit instead.',
E_USER_DEPRECATED
);
}
$this->preSubmit($event);
}
/**
* @param FormEvent $event
*/
public function preSubmit(FormEvent $event)
{
$data = $event->getData();
$transformers = $event->getForm()->getConfig()->getViewTransformers();
if (count($transformers) === 1 && $transformers[0] instanceof BooleanToStringTransformer && $data === '0') {
$event->setData(null);
}
}
}

View File

@@ -0,0 +1,241 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
/**
* Resize a collection form element based on the data sent from the client.
*
* @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
*/
class ResizeFormListener implements EventSubscriberInterface
{
/**
* @var string
*/
private $type;
/**
* @var bool
*/
private $resizeOnSubmit;
/**
* @var array
*/
private $typeOptions;
/**
* @var string[]
*/
private $removed = array();
/**
* @var \Closure
*/
private $preSubmitDataCallback;
/**
* @param string $type
* @param array $typeOptions
* @param bool $resizeOnSubmit
* @param \Closure|null $preSubmitDataCallback
*/
public function __construct($type, array $typeOptions = array(), $resizeOnSubmit = false, $preSubmitDataCallback = null)
{
$this->type = $type;
$this->resizeOnSubmit = $resizeOnSubmit;
$this->typeOptions = $typeOptions;
$this->preSubmitDataCallback = $preSubmitDataCallback;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
// NEXT_MAJOR: change `preBind` to `preSubmit`
FormEvents::PRE_SUBMIT => 'preBind',
// NEXT_MAJOR: change `onBind` to `onSubmit`
FormEvents::SUBMIT => 'onBind',
);
}
/**
* @param FormEvent $event
*
* @throws UnexpectedTypeException
*/
public function preSetData(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
if (null === $data) {
$data = array();
}
if (!is_array($data) && !$data instanceof \Traversable) {
throw new UnexpectedTypeException($data, 'array or \Traversable');
}
// First remove all rows except for the prototype row
foreach ($form as $name => $child) {
$form->remove($name);
}
// Then add all rows again in the correct order
foreach ($data as $name => $value) {
$options = array_merge($this->typeOptions, array(
'property_path' => '['.$name.']',
'data' => $value,
));
$form->add($name, $this->type, $options);
}
}
/**
* NEXT_MAJOR: remove this method.
*
* @param FormEvent $event
*
* @deprecated Since version 2.3, to be renamed in 4.0.
* Use {@link preSubmit} instead
*/
public function preBind(FormEvent $event)
{
// BC prevention for class extending this one.
if (get_called_class() !== 'Sonata\CoreBundle\Form\EventListener\ResizeFormListener') {
@trigger_error(
__METHOD__.' method is deprecated since 2.3 and will be renamed in 4.0.'
.' Use '.__CLASS__.'::preSubmit instead.',
E_USER_DEPRECATED
);
}
$this->preSubmit($event);
}
/**
* @param FormEvent $event
*
* @throws UnexpectedTypeException
*/
public function preSubmit(FormEvent $event)
{
if (!$this->resizeOnSubmit) {
return;
}
$form = $event->getForm();
$data = $event->getData();
if (null === $data || '' === $data) {
$data = array();
}
if (!is_array($data) && !$data instanceof \Traversable) {
throw new UnexpectedTypeException($data, 'array or \Traversable');
}
// Remove all empty rows except for the prototype row
foreach ($form as $name => $child) {
$form->remove($name);
}
// Add all additional rows
foreach ($data as $name => $value) {
if (!$form->has($name)) {
$buildOptions = array(
'property_path' => '['.$name.']',
);
if ($this->preSubmitDataCallback) {
$buildOptions['data'] = call_user_func($this->preSubmitDataCallback, $value);
}
$options = array_merge($this->typeOptions, $buildOptions);
$form->add($name, $this->type, $options);
}
if (isset($value['_delete'])) {
$this->removed[] = $name;
}
}
}
/**
* NEXT_MAJOR: remove this method.
*
* @param FormEvent $event
*
* @deprecated Since version 2.3, to be removed in 4.0.
* Use {@link onSubmit} instead
*/
public function onBind(FormEvent $event)
{
// BC prevention for class extending this one.
if (get_called_class() !== 'Sonata\CoreBundle\Form\EventListener\ResizeFormListener') {
@trigger_error(
__METHOD__.' is deprecated since 2.3 and will be renamed in 4.0.'
.' Use '.__CLASS__.'::onSubmit instead.',
E_USER_DEPRECATED
);
}
$this->onSubmit($event);
}
/**
* @param FormEvent $event
*
* @throws UnexpectedTypeException
*/
public function onSubmit(FormEvent $event)
{
if (!$this->resizeOnSubmit) {
return;
}
$form = $event->getForm();
$data = $event->getData();
if (null === $data) {
$data = array();
}
if (!is_array($data) && !$data instanceof \Traversable) {
throw new UnexpectedTypeException($data, 'array or \Traversable');
}
foreach ($data as $name => $child) {
if (!$form->has($name)) {
unset($data[$name]);
}
}
// remove selected elements
foreach ($this->removed as $pos) {
unset($data[$pos]);
}
$event->setData($data);
}
}

View File

@@ -0,0 +1,209 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Extension;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\FormExtensionInterface;
use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\Form\FormTypeGuesserInterface;
/**
* This proxy class help to keep BC code with < SF2.8 form behavior by restoring
* the type as a code and not as a class.
*/
class DependencyInjectionExtension implements FormExtensionInterface
{
/**
* @var FormExtensionInterface
*/
protected $extension;
/**
* @var array
*/
protected $mappingTypes;
/**
* @var array
*/
protected $extensionTypes;
/**
* @var ContainerInterface
*/
private $container;
/**
* @var string[]
*/
private $typeServiceIds;
/**
* @var string[]
*/
private $typeExtensionServiceIds;
/**
* @var string[]
*/
private $guesserServiceIds;
/**
* @var FormTypeGuesserInterface
*/
private $guesser;
/**
* @var bool
*/
private $guesserLoaded = false;
/**
* @param ContainerInterface $container
* @param array $typeServiceIds
* @param array $typeExtensionServiceIds
* @param array $guesserServiceIds
* @param array $mappingTypes
* @param array $extensionTypes
*/
public function __construct(ContainerInterface $container, array $typeServiceIds, array $typeExtensionServiceIds, array $guesserServiceIds, array $mappingTypes = array(), array $extensionTypes = array())
{
$this->container = $container;
$this->typeServiceIds = $typeServiceIds;
$this->typeExtensionServiceIds = $typeExtensionServiceIds;
$this->guesserServiceIds = $guesserServiceIds;
$this->mappingTypes = $mappingTypes;
$this->mappingExtensionTypes = $extensionTypes;
$this->reverseMappingTypes = array_flip($mappingTypes);
}
/**
* {@inheritdoc}
*/
public function getType($name)
{
// resolve code to FQCN
$name = self::findClass($this->mappingTypes, $name);
if (!isset($this->typeServiceIds[$name])) {
if (class_exists($name) && in_array('Symfony\Component\Form\FormTypeInterface', class_implements($name), true)) {
return new $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 ($name !== get_class($type) && (method_exists($type, 'getName') && $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,
get_class($type)
));
}
return $type;
}
/**
* {@inheritdoc}
*/
public function hasType($name)
{
return isset($this->mappingTypes[$name]) || isset($this->typeServiceIds[$name]);
}
/**
* {@inheritdoc}
*/
public function getTypeExtensions($name)
{
// lookup inside the extension mapping
$serviceIdx = array();
if (isset($this->reverseMappingTypes[$name])) {
$code = $this->reverseMappingTypes[$name];
if (isset($this->mappingExtensionTypes[$code])) {
$serviceIdx = array_merge($serviceIdx, $this->mappingExtensionTypes[$code]);
}
}
$serviceIdx = array_unique(array_merge(isset($this->typeExtensionServiceIds[$name]) ? $this->typeExtensionServiceIds[$name] : array(), $serviceIdx));
$extensions = array();
foreach ($serviceIdx as $serviceId) {
if ($this->container->has($serviceId)) {
$extensions[] = $this->container->get($serviceId);
}
}
return $extensions;
}
/**
* {@inheritdoc}
*/
public function hasTypeExtensions($name)
{
return isset($this->reverseMappingTypes[$name]) || isset($this->typeExtensionServiceIds[$name]);
}
/**
* {@inheritdoc}
*/
public function getTypeGuesser()
{
if (!$this->guesserLoaded) {
$this->guesserLoaded = true;
$guessers = array();
foreach ($this->guesserServiceIds as $serviceId) {
if ($this->container->has($serviceId)) {
$guessers[] = $this->container->get($serviceId);
}
}
if ($guessers) {
$this->guesser = new FormTypeGuesserChain($guessers);
}
}
return $this->guesser;
}
/**
* @param string $type
*
* @return string
*/
protected static function findClass($mapping, $type)
{
if (strpos($type, '\\')) {
return $type;
}
if (!isset($mapping[$type])) {
return $type;
}
return $mapping[$type];
}
}

View File

@@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class FormHelper
{
private static $typeMapping = array();
private static $extensionMapping = array();
/**
* This function remove fields available if there are not present in the $data array
* The data array might come from $request->request->all().
*
* This can be usefull if you don't want to send all fields will building an api. As missing
* fields will be threated like null values.
*
* @param array $data
* @param Form $form
*/
public static function removeFields(array $data, Form $form)
{
$diff = array_diff(array_keys($form->all()), array_keys($data));
foreach ($diff as $key) {
$form->remove($key);
}
foreach ($data as $name => $value) {
if (!is_array($value)) {
continue;
}
self::removeFields($value, $form[$name]);
}
}
/**
* @return array
*/
public static function getFormExtensionMapping()
{
return self::$extensionMapping;
}
/**
* @param array $mapping
*/
public static function registerFormTypeMapping(array $mapping)
{
self::$typeMapping = array_merge(self::$typeMapping, $mapping);
}
/**
* @param string $type
* @param array $services
*/
public static function registerFormExtensionMapping($type, array $services)
{
if (!isset(self::$extensionMapping[$type])) {
self::$extensionMapping[$type] = array();
}
self::$extensionMapping[$type] = array_merge(self::$extensionMapping[$type], $services);
}
/**
* @return array
*/
public static function getFormTypeMapping()
{
return self::$typeMapping;
}
/**
* @param FormTypeInterface $type
* @param OptionsResolver $optionsResolver
*
* @internal
*/
public static function configureOptions(FormTypeInterface $type, OptionsResolver $optionsResolver)
{
if (!method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')) {
$type->setDefaultOptions($optionsResolver);
} else { // SF <2.8 BC
$type->configureOptions($optionsResolver);
}
}
}

View File

@@ -0,0 +1,180 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Doctrine\Common\Persistence\ManagerRegistry;
use Metadata\MetadataFactoryInterface;
use Sonata\CoreBundle\Form\EventListener\FixCheckboxDataListener;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* This is a doctrine serialization form type that generates a form type from class serialization metadata
* and doctrine metadata.
*
* @author Vincent Composieux <vincent.composieux@gmail.com>
*/
class BaseDoctrineORMSerializationType extends AbstractType
{
/**
* @var RegistryInterface
*/
protected $registry;
/**
* @var MetadataFactoryInterface
*/
protected $metadataFactory;
/**
* @var string
*/
protected $name;
/**
* @var string
*/
protected $class;
/**
* @var string
*/
protected $group;
/**
* @var bool
*/
protected $identifierOverwrite;
/**
* @param MetadataFactoryInterface $metadataFactory Serializer metadata factory
* @param ManagerRegistry $registry Doctrine registry
* @param string $name Form type name
* @param string $class Data class name
* @param string $group Serialization group name
* @param bool|false $identifierOverwrite
*/
public function __construct(MetadataFactoryInterface $metadataFactory, ManagerRegistry $registry, $name, $class, $group, $identifierOverwrite = false)
{
$this->metadataFactory = $metadataFactory;
$this->registry = $registry;
$this->name = $name;
$this->class = $class;
$this->group = $group;
$this->identifierOverwrite = $identifierOverwrite;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$serializerMetadata = $this->metadataFactory->getMetadataForClass($this->class);
$manager = $this->registry->getManagerForClass($this->class);
$doctrineMetadata = $manager->getClassMetadata($this->class);
foreach ($serializerMetadata->propertyMetadata as $propertyMetadata) {
$name = $propertyMetadata->name;
if (in_array($name, $doctrineMetadata->getIdentifierFieldNames(), true) && !$this->identifierOverwrite) {
continue;
}
if (!$propertyMetadata->groups || !in_array($this->group, $propertyMetadata->groups, true)) {
continue;
}
$type = null;
$nullable = true;
if (isset($doctrineMetadata->fieldMappings[$name])) {
$fieldMetadata = $doctrineMetadata->fieldMappings[$name];
$type = isset($fieldMetadata['type']) ? $fieldMetadata['type'] : null;
$nullable = isset($fieldMetadata['nullable']) ? $fieldMetadata['nullable'] : false;
} elseif (isset($doctrineMetadata->associationMappings[$name])) {
$associationMetadata = $doctrineMetadata->associationMappings[$name];
if (isset($associationMetadata['joinColumns']['nullable'])) {
$nullable = $associationMetadata['joinColumns']['nullable'];
} elseif (isset($associationMetadata['inverseJoinColumns']['nullable'])) {
$nullable = $associationMetadata['inverseJoinColumns']['nullable'];
}
}
switch ($type) {
case 'datetime':
$builder->add(
$name,
// NEXT_MAJOR: Remove ternary and keep 'Symfony\Component\Form\Extension\Core\Type\DateTimeType'
// (when requirement of Symfony is >= 2.8)
method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Symfony\Component\Form\Extension\Core\Type\DateTimeType'
: 'datetime',
array('required' => !$nullable, 'widget' => 'single_text')
);
break;
case 'boolean':
$childBuilder = $builder->create($name, null, array('required' => !$nullable));
$childBuilder->addEventSubscriber(new FixCheckboxDataListener());
$builder->add($childBuilder);
break;
default:
$builder->add($name, null, array('required' => !$nullable));
break;
}
}
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return $this->name;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => $this->class,
));
}
}

View File

@@ -0,0 +1,151 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Sonata\CoreBundle\Date\MomentFormatConverter;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Class BasePickerType (to factorize DatePickerType and DateTimePickerType code.
*
* @author Hugo Briand <briand@ekino.com>
*/
abstract class BasePickerType extends AbstractType
{
/**
* @var TranslatorInterface
*/
protected $translator;
/**
* @var string
*/
protected $locale;
/**
* @var MomentFormatConverter
*/
private $formatConverter;
/**
* NEXT_MAJOR: TranslatorInterface needs to be mandatory.
*
* @param MomentFormatConverter $formatConverter
* @param TranslatorInterface $translator
*/
public function __construct(MomentFormatConverter $formatConverter, TranslatorInterface $translator = null)
{
$this->formatConverter = $formatConverter;
$this->translator = $translator;
/*
* NEXT_MAJOR: remove this check
*/
if (null === $this->translator) {
@trigger_error(
'Initializing '.__CLASS__.' without TranslatorInterface
is deprecated since 2.4 and will be removed in 4.0.',
E_USER_DEPRECATED
);
$this->locale = \Locale::getDefault();
return;
}
$this->locale = $this->translator->getLocale();
}
/**
* {@inheritdoc}
*/
public function finishView(FormView $view, FormInterface $form, array $options)
{
$format = $options['format'];
if (isset($options['date_format']) && is_string($options['date_format'])) {
$format = $options['date_format'];
} elseif (is_int($format)) {
$timeFormat = ($options['dp_pick_time']) ? DateTimeType::DEFAULT_TIME_FORMAT : \IntlDateFormatter::NONE;
$intlDateFormatter = new \IntlDateFormatter(
\Locale::getDefault(),
$format,
$timeFormat,
null,
\IntlDateFormatter::GREGORIAN,
null
);
$format = $intlDateFormatter->getPattern();
}
// use seconds if it's allowed in format
$options['dp_use_seconds'] = strpos($format, 's') !== false;
$view->vars['moment_format'] = $this->formatConverter->convert($format);
$view->vars['type'] = 'text';
$dpOptions = array();
foreach ($options as $key => $value) {
if (false !== strpos($key, 'dp_')) {
// We remove 'dp_' and camelize the options names
$dpKey = substr($key, 3);
$dpKey = preg_replace_callback('/_([a-z])/', function ($c) {
return strtoupper($c[1]);
}, $dpKey);
$dpOptions[$dpKey] = $value;
}
}
$view->vars['datepicker_use_button'] = empty($options['datepicker_use_button']) ? false : true;
$view->vars['dp_options'] = $dpOptions;
}
/**
* Gets base default options for the date pickers.
*
* @return array
*/
protected function getCommonDefaults()
{
return array(
'widget' => 'single_text',
'datepicker_use_button' => true,
'dp_pick_time' => true,
'dp_use_current' => true,
'dp_min_date' => '1/1/1900',
'dp_max_date' => null,
'dp_show_today' => true,
'dp_language' => $this->locale,
'dp_default_date' => '',
'dp_disabled_dates' => array(),
'dp_enabled_dates' => array(),
'dp_icons' => array(
'time' => 'fa fa-clock-o',
'date' => 'fa fa-calendar',
'up' => 'fa fa-chevron-up',
'down' => 'fa fa-chevron-down',
),
'dp_use_strict' => false,
'dp_side_by_side' => false,
'dp_days_of_week_disabled' => array(),
'dp_collapse' => true,
'dp_calendar_weeks' => false,
'dp_view_mode' => 'days',
'dp_min_view_mode' => 'days',
);
}
}

View File

@@ -0,0 +1,113 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
abstract class BaseStatusType extends AbstractType
{
/**
* @var string
*/
protected $class;
/**
* @var string
*/
protected $getter;
/**
* @var string
*/
protected $name;
/**
* @var bool
*/
protected $flip;
/**
* @param string $class
* @param string $getter
* @param string $name
* @param bool $flip reverse key/value to match sf2.8 and sf3.0 change
*/
public function __construct($class, $getter, $name, $flip = false)
{
$this->class = $class;
$this->getter = $getter;
$this->name = $name;
$this->flip = $flip;
}
/**
* {@inheritdoc}
*/
public function getParent()
{
// NEXT_MAJOR: Remove ternary and keep 'Symfony\Component\Form\Extension\Core\Type\ChoiceType'
// (when requirement of Symfony is >= 2.8)
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Symfony\Component\Form\Extension\Core\Type\ChoiceType'
: 'choice';
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return $this->name;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$choices = call_user_func(array($this->class, $this->getter));
if ($this->flip) {
$count = count($choices);
$choices = array_flip($choices);
if (count($choices) !== $count) {
throw new \RuntimeException('Unable to safely flip value as final count is different');
}
}
$resolver->setDefaults(array(
'choices' => $choices,
));
}
}

View File

@@ -0,0 +1,127 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Sonata\CoreBundle\Form\DataTransformer\BooleanTypeToBooleanTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class BooleanType extends AbstractType
{
const TYPE_YES = 1;
const TYPE_NO = 2;
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['transform']) {
$builder->addModelTransformer(new BooleanTypeToBooleanTransformer());
}
if ($options['catalogue'] !== 'SonataCoreBundle') {
@trigger_error(
'Option "catalogue" is deprecated since SonataCoreBundle 2.3.10 and will be removed in 4.0.'
.' Use option "translation_domain" instead.',
E_USER_DEPRECATED
);
}
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$choices = array(
self::TYPE_YES => 'label_type_yes',
self::TYPE_NO => 'label_type_no',
);
$defaultOptions = array(
'transform' => false,
/*
* NEXT_MAJOR: remove this block.
* @deprecated Deprecated as of SonataCoreBundle 2.3.10, to be removed in 4.0.
*/
'catalogue' => 'SonataCoreBundle',
// Use directly translation_domain in SonataCoreBundle 4.0
'translation_domain' => function (Options $options) {
if ($options['catalogue']) {
return $options['catalogue'];
}
return $options['translation_domain'];
},
);
// NEXT_MAJOR: Remove this "if" (when requirement of Symfony is >= 2.7)
if (method_exists('Symfony\Component\Form\AbstractType', 'configureOptions')) {
$choices = array_flip($choices);
$defaultOptions['choice_translation_domain'] = 'SonataCoreBundle';
// choice_as_value options is not needed in SF 3.0+
if (method_exists('Symfony\Component\Form\FormTypeInterface', 'setDefaultOptions')) {
$defaultOptions['choices_as_values'] = true;
}
}
$defaultOptions['choices'] = $choices;
$resolver->setDefaults($defaultOptions);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\ChoiceType' :
'choice' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_boolean';
}
}

View File

@@ -0,0 +1,92 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Sonata\CoreBundle\Form\EventListener\ResizeFormListener;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CollectionType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$listener = new ResizeFormListener(
$options['type'],
$options['type_options'],
$options['modifiable'],
$options['pre_bind_data_callback']
);
$builder->addEventSubscriber($listener);
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['btn_add'] = $options['btn_add'];
$view->vars['btn_catalogue'] = $options['btn_catalogue'];
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'modifiable' => false,
// NEXT_MAJOR: Remove ternary and keep 'Symfony\Component\Form\Extension\Core\Type\TextType'
// (when requirement of Symfony is >= 2.8)
'type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Symfony\Component\Form\Extension\Core\Type\TextType'
: 'text',
'type_options' => array(),
'pre_bind_data_callback' => null,
'btn_add' => 'link_add',
'btn_catalogue' => 'SonataCoreBundle',
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_collection';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,92 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Sonata\CoreBundle\Color\Colors;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
@trigger_error(
'The '.__NAMESPACE__.'\ColorSelectorType class is deprecated since version 3.5 and will be removed in 4.0.'
.' Use '.__NAMESPACE__.'\ColorType instead.',
E_USER_DEPRECATED
);
/**
* NEXT_MAJOR: remove this class.
*
* @deprecated since version 3.5, to be removed in 4.0. Use ColorType instead
*/
class ColorSelectorType extends AbstractType
{
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => array_flip(Colors::getAll()),
'choices_as_values' => true,
'translation_domain' => 'SonataCoreBundle',
'preferred_choices' => array(
Colors::BLACK,
Colors::BLUE,
Colors::GRAY,
Colors::GREEN,
Colors::ORANGE,
Colors::PINK,
Colors::PURPLE,
Colors::RED,
Colors::WHITE,
Colors::YELLOW,
),
));
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\ChoiceType' :
'choice' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_color_selector';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
final class ColorType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\TextType' :
'text' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_color';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,70 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* @author Hugo Briand <briand@ekino.com>
*/
class DatePickerType extends BasePickerType
{
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array_merge($this->getCommonDefaults(), array(
'dp_pick_time' => false,
'format' => DateType::DEFAULT_FORMAT,
)));
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\DateType' :
'date' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_date_picker';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* DateRangePickerType.
*
* @author Andrej Hudec <pulzarraider@gmail.com>
*/
class DateRangePickerType extends DateRangeType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'field_options' => array(),
'field_options_start' => array(),
'field_options_end' => array(),
// NEXT_MAJOR: Remove ternary and keep 'Sonata\CoreBundle\Form\Type\DatePickerType'
// (when requirement of Symfony is >= 2.8)
'field_type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Sonata\CoreBundle\Form\Type\DatePickerType'
: 'sonata_type_date_picker',
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_date_range_picker';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,119 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Translation\TranslatorInterface;
class DateRangeType extends AbstractType
{
/**
* NEXT_MAJOR: remove this property.
*
* @var TranslatorInterface|null
*
* @deprecated translator property is deprecated since version 3.1, to be removed in 4.0
*/
protected $translator;
/**
* NEXT_MAJOR: remove this method.
*
* @param TranslatorInterface|null $translator
*
* @deprecated translator dependency is deprecated since version 3.1, to be removed in 4.0
*/
public function __construct(TranslatorInterface $translator = null)
{
// check if class is overloaded and notify about removing deprecated translator
if ($translator !== null && get_class($this) !== get_class() && get_class($this) !== 'Sonata\CoreBundle\Form\Type\DateRangePickerType') {
@trigger_error(
'The translator dependency in '.__CLASS__.' is deprecated since 3.1 and will be removed in 4.0. '.
'Please prepare your dependencies for this change.',
E_USER_DEPRECATED
);
}
$this->translator = $translator;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$options['field_options_start'] = array_merge(
array(
'label' => 'date_range_start',
'translation_domain' => 'SonataCoreBundle',
),
$options['field_options_start']
);
$options['field_options_end'] = array_merge(
array(
'label' => 'date_range_end',
'translation_domain' => 'SonataCoreBundle',
),
$options['field_options_end']
);
$builder->add('start', $options['field_type'], array_merge(array('required' => false), $options['field_options'], $options['field_options_start']));
$builder->add('end', $options['field_type'], array_merge(array('required' => false), $options['field_options'], $options['field_options_end']));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_date_range';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'field_options' => array(),
'field_options_start' => array(),
'field_options_end' => array(),
// NEXT_MAJOR: Remove ternary and keep 'Symfony\Component\Form\Extension\Core\Type\DateType'
// (when requirement of Symfony is >= 2.8)
'field_type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Symfony\Component\Form\Extension\Core\Type\DateType'
: 'date',
));
}
}

View File

@@ -0,0 +1,73 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* @author Hugo Briand <briand@ekino.com>
*/
class DateTimePickerType extends BasePickerType
{
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array_merge($this->getCommonDefaults(), array(
'dp_use_minutes' => true,
'dp_use_seconds' => true,
'dp_minute_stepping' => 1,
'format' => DateTimeType::DEFAULT_DATE_FORMAT,
'date_format' => null,
)));
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\DateTimeType' :
'datetime' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_datetime_picker';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* DateTimeRangePickerType.
*
* @author Andrej Hudec <pulzarraider@gmail.com>
*/
class DateTimeRangePickerType extends DateTimeRangeType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'field_options' => array(),
'field_options_start' => array(),
'field_options_end' => array(),
// NEXT_MAJOR: Remove ternary and keep 'Sonata\CoreBundle\Form\Type\DateTimePickerType'
// (when requirement of Symfony is >= 2.8)
'field_type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Sonata\CoreBundle\Form\Type\DateTimePickerType'
: 'sonata_type_datetime_picker',
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_datetime_range_picker';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,119 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Translation\TranslatorInterface;
class DateTimeRangeType extends AbstractType
{
/**
* NEXT_MAJOR: remove this property.
*
* @var TranslatorInterface|null
*
* @deprecated translator property is deprecated since version 3.1, to be removed in 4.0
*/
protected $translator;
/**
* NEXT_MAJOR: remove this method.
*
* @param TranslatorInterface|null $translator
*
* @deprecated translator dependency is deprecated since version 3.1, to be removed in 4.0
*/
public function __construct(TranslatorInterface $translator = null)
{
// check if class is overloaded and notify about removing deprecated translator
if ($translator !== null && get_class($this) !== get_class() && get_class($this) !== 'Sonata\CoreBundle\Form\Type\DateTimeRangePickerType') {
@trigger_error(
'The translator dependency in '.__CLASS__.' is deprecated since 3.1 and will be removed in 4.0. '.
'Please prepare your dependencies for this change.',
E_USER_DEPRECATED
);
}
$this->translator = $translator;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$options['field_options_start'] = array_merge(
array(
'label' => 'date_range_start',
'translation_domain' => 'SonataCoreBundle',
),
$options['field_options_start']
);
$options['field_options_end'] = array_merge(
array(
'label' => 'date_range_end',
'translation_domain' => 'SonataCoreBundle',
),
$options['field_options_end']
);
$builder->add('start', $options['field_type'], array_merge(array('required' => false), $options['field_options'], $options['field_options_start']));
$builder->add('end', $options['field_type'], array_merge(array('required' => false), $options['field_options'], $options['field_options_end']));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_datetime_range';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'field_options' => array(),
'field_options_start' => array(),
'field_options_end' => array(),
// NEXT_MAJOR: Remove ternary and keep 'Symfony\Component\Form\Extension\Core\Type\DateTimeType'
// (when requirement of Symfony is >= 2.8)
'field_type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
? 'Symfony\Component\Form\Extension\Core\Type\DateTimeType'
: 'datetime',
));
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
/**
* NEXT_MAJOR: remove this class.
*
* @deprecated Class to be remove once we only support Symfony3.X
*/
class DoctrineORMSerializationType extends BaseDoctrineORMSerializationType
{
}

View File

@@ -0,0 +1,120 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Translation\TranslatorInterface;
class EqualType extends AbstractType
{
const TYPE_IS_EQUAL = 1;
const TYPE_IS_NOT_EQUAL = 2;
/**
* NEXT_MAJOR: remove this property.
*
* @var TranslatorInterface|null
*
* @deprecated translator property is deprecated since version 3.1, to be removed in 4.0
*/
protected $translator;
/**
* NEXT_MAJOR: remove this method.
*
* @param TranslatorInterface|null $translator
*
* @deprecated translator property is deprecated since version 3.1, to be removed in 4.0
*/
public function __construct(TranslatorInterface $translator = null)
{
// check if class is overloaded and notify about removing deprecated translator
if ($translator !== null && get_class($this) !== get_class()) {
@trigger_error(
'The translator dependency in '.__CLASS__.' is deprecated since 3.1 and will be removed in 4.0. '.
'Please prepare your dependencies for this change.',
E_USER_DEPRECATED
);
}
$this->translator = $translator;
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$choices = array(
self::TYPE_IS_EQUAL => 'label_type_equals',
self::TYPE_IS_NOT_EQUAL => 'label_type_not_equals',
);
$defaultOptions = array(
'choice_translation_domain' => 'SonataCoreBundle',
);
// SF 2.7+ BC
if (method_exists('Symfony\Component\Form\AbstractType', 'configureOptions')) {
$choices = array_flip($choices);
// choice_as_value options is not needed in SF 3.0+
if (method_exists('Symfony\Component\Form\FormTypeInterface', 'setDefaultOptions')) {
$defaultOptions['choices_as_values'] = true;
}
}
$defaultOptions['choices'] = $choices;
$resolver->setDefaults($defaultOptions);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\ChoiceType' :
'choice' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_equal';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,99 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ImmutableArrayType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($options['keys'] as $infos) {
if ($infos instanceof FormBuilderInterface) {
$builder->add($infos);
} else {
list($name, $type, $options) = $infos;
if (is_callable($options)) {
$extra = array_slice($infos, 3);
$options = $options($builder, $name, $type, $extra);
if ($options === null) {
$options = array();
} elseif (!is_array($options)) {
throw new \RuntimeException('the closure must return null or an array');
}
}
$builder->add($name, $type, $options);
}
}
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'keys' => array(),
));
// NEXT_MAJOR: remove the condition
if (!method_exists('Symfony\Component\OptionsResolver\OptionsResolver', 'setDefault')) {
return;
}
$resolver->setAllowedValues('keys', function ($value) {
foreach ($value as $subValue) {
if (!$subValue instanceof FormBuilderInterface && (!is_array($subValue) || count($subValue) !== 3)) {
return false;
}
}
return true;
});
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_immutable_array';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
/**
* NEXT_MAJOR: remove this class.
*
* @deprecated Class to be remove once we only support Symfony3.X
*/
class StatusType extends BaseStatusType
{
}

View File

@@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Translation\TranslatorInterface;
/**
* NEXT_MAJOR: remove this class.
*
* @deprecated Deprecated as of SonataCoreBundle 2.2.0, to be removed in 4.0.
* Use form type "choice" with "translation_domain" option instead
*/
class TranslatableChoiceType extends AbstractType
{
/**
* @var TranslatorInterface
*/
protected $translator;
/**
* @param TranslatorInterface $translator
*/
public function __construct(TranslatorInterface $translator)
{
@trigger_error(
'Form type "sonata_type_translatable_choice" is deprecated since SonataCoreBundle 2.2.0 and will be'
.' removed in 4.0. Use form type "choice" with "translation_domain" option instead.',
E_USER_DEPRECATED
);
$this->translator = $translator;
}
/**
* {@inheritdoc}
*
* @todo Remove it when bumping requirements to SF 2.7+
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$this->configureOptions($resolver);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'catalogue' => 'messages',
));
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['translation_domain'] = $options['catalogue'];
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix') ?
'Symfony\Component\Form\Extension\Core\Type\ChoiceType' :
'choice' // SF <2.8 BC
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'sonata_type_translatable_choice';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
}