fix symfony 2.8 deprecation warnings
This commit is contained in:
parent
70807641c7
commit
0b31960534
210
Form/ChoiceList/PropelChoiceLoader.php
Normal file
210
Form/ChoiceList/PropelChoiceLoader.php
Normal file
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the PropelBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Propel\Bundle\PropelBundle\Form\ChoiceList;
|
||||
|
||||
use ColumnMap;
|
||||
use ModelCriteria;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
|
||||
/**
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
* @author Toni Uebernickel <tuebernickel@gmail.com>
|
||||
* @author Moritz Schroeder <moritz.schroeder@molabs.de>
|
||||
*/
|
||||
class PropelChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
/**
|
||||
* @var ChoiceListFactoryInterface
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
/**
|
||||
* @var ModelCriteria
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* The fields of which the identifier of the underlying class consists
|
||||
*
|
||||
* This property should only be accessed through identifier.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $identifier = array();
|
||||
|
||||
/**
|
||||
* Whether to use the identifier for index generation.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $identifierAsIndex = false;
|
||||
|
||||
/**
|
||||
* @var ChoiceListInterface
|
||||
*/
|
||||
protected $choiceList;
|
||||
|
||||
/**
|
||||
* PropelChoiceListLoader constructor.
|
||||
*
|
||||
* @param ChoiceListFactoryInterface $factory
|
||||
* @param string $class
|
||||
*/
|
||||
public function __construct(ChoiceListFactoryInterface $factory, $class, ModelCriteria $queryObject, $useAsIdentifier = null)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
$this->class = $class;
|
||||
$this->query = $queryObject;
|
||||
if ($useAsIdentifier) {
|
||||
$this->identifier = array($this->query->getTableMap()->getColumn($useAsIdentifier));
|
||||
} else {
|
||||
$this->identifier = $this->query->getTableMap()->getPrimaryKeys();
|
||||
}
|
||||
if (1 === count($this->identifier) && $this->isScalar(current($this->identifier))) {
|
||||
$this->identifierAsIndex = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadChoiceList($value = null)
|
||||
{
|
||||
if ($this->choiceList) {
|
||||
return $this->choiceList;
|
||||
}
|
||||
|
||||
$models = iterator_to_array($this->query->find());
|
||||
|
||||
$this->choiceList = $this->factory->createListFromChoices($models, $value);
|
||||
|
||||
return $this->choiceList;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadChoicesForValues(array $values, $value = null)
|
||||
{
|
||||
// Performance optimization
|
||||
if (empty($values)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Optimize performance in case we have a single-field identifier
|
||||
if (!$this->choiceList && $this->identifierAsIndex && current($this->identifier) instanceof ColumnMap) {
|
||||
$phpName = current($this->identifier)->getPhpName();
|
||||
$unorderedObjects = $this->query->filterBy($phpName, $values);
|
||||
$objectsById = array();
|
||||
$objects = array();
|
||||
|
||||
// Maintain order and indices from the given $values
|
||||
foreach ($unorderedObjects as $object) {
|
||||
$objectsById[(string) current($this->getIdentifierValues($object))] = $object;
|
||||
}
|
||||
|
||||
foreach ($values as $i => $id) {
|
||||
if (isset($objectsById[$id])) {
|
||||
$objects[$i] = $objectsById[$id];
|
||||
}
|
||||
}
|
||||
|
||||
return $objects;
|
||||
}
|
||||
|
||||
return $this->loadChoiceList($value)->getChoicesForValues($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadValuesForChoices(array $choices, $value = null)
|
||||
{
|
||||
// Performance optimization
|
||||
if (empty($choices)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!$this->choiceList && $this->identifierAsIndex) {
|
||||
$values = array();
|
||||
|
||||
// Maintain order and indices of the given objects
|
||||
foreach ($choices as $i => $object) {
|
||||
if ($object instanceof $this->class) {
|
||||
// Make sure to convert to the right format
|
||||
$values[$i] = (string) current($this->getIdentifierValues($object));
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $this->loadChoiceList($value)->getValuesForChoices($choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this column contains scalar values (to be used as indices).
|
||||
*
|
||||
* @param ColumnMap $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isScalar(ColumnMap $column)
|
||||
{
|
||||
return in_array(
|
||||
$column->getPdoType(),
|
||||
array(
|
||||
\PDO::PARAM_BOOL,
|
||||
\PDO::PARAM_INT,
|
||||
\PDO::PARAM_STR,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values of the identifier fields of a model.
|
||||
*
|
||||
* Propel must know about this model, that is, the model must already
|
||||
* be persisted or added to the idmodel map before. Otherwise an
|
||||
* exception is thrown.
|
||||
*
|
||||
* @param object $model The model for which to get the identifier
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getIdentifierValues($model)
|
||||
{
|
||||
if (!$model instanceof $this->class) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (1 === count($this->identifier) && current($this->identifier) instanceof ColumnMap) {
|
||||
$phpName = current($this->identifier)->getPhpName();
|
||||
if (method_exists($model, 'get' . $phpName)) {
|
||||
return array($model->{'get' . $phpName}());
|
||||
}
|
||||
}
|
||||
|
||||
if ($model instanceof \BaseObject) {
|
||||
return array($model->getPrimaryKey());
|
||||
}
|
||||
|
||||
return $model->getPrimaryKeys();
|
||||
}
|
||||
|
||||
}
|
|
@ -12,7 +12,11 @@
|
|||
namespace Propel\Bundle\PropelBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractExtension;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
/**
|
||||
* Represents the Propel form extension, which loads the Propel functionality.
|
||||
|
@ -21,10 +25,33 @@ use Symfony\Component\PropertyAccess\PropertyAccess;
|
|||
*/
|
||||
class PropelExtension extends AbstractExtension
|
||||
{
|
||||
|
||||
/**
|
||||
* @var PropertyAccessorInterface
|
||||
*/
|
||||
protected $propertyAccessor;
|
||||
|
||||
/**
|
||||
* @var ChoiceListFactoryInterface
|
||||
*/
|
||||
protected $choiceListFactory;
|
||||
|
||||
/**
|
||||
* PropelExtension constructor.
|
||||
*
|
||||
* @param PropertyAccessorInterface|null $propertyAccessor
|
||||
* @param ChoiceListFactoryInterface|null $choiceListFactory
|
||||
*/
|
||||
public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null)
|
||||
{
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||
$this->choiceListFactory = $choiceListFactory ?: new PropertyAccessDecorator(new DefaultChoiceListFactory(), $this->propertyAccessor);
|
||||
|
||||
}
|
||||
protected function loadTypes()
|
||||
{
|
||||
return array(
|
||||
new Type\ModelType(PropertyAccess::createPropertyAccessor()),
|
||||
new Type\ModelType($this->propertyAccessor, $this->choiceListFactory),
|
||||
new Type\TranslationCollectionType(),
|
||||
new Type\TranslationType(),
|
||||
);
|
||||
|
|
|
@ -11,14 +11,20 @@
|
|||
|
||||
namespace Propel\Bundle\PropelBundle\Form\Type;
|
||||
|
||||
use Propel\Bundle\PropelBundle\Form\ChoiceList\ModelChoiceList;
|
||||
use Propel\Bundle\PropelBundle\Form\ChoiceList\PropelChoiceLoader;
|
||||
use Propel\Bundle\PropelBundle\Form\DataTransformer\CollectionToArrayTransformer;
|
||||
use ModelCriteria;
|
||||
use ColumnMap;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
|
||||
use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
|
||||
use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;
|
||||
|
||||
/**
|
||||
* ModelType class.
|
||||
|
@ -51,78 +57,202 @@ use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
|||
class ModelType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var PropertyAccessorInterface
|
||||
* @var ChoiceListFactoryInterface
|
||||
*/
|
||||
private $propertyAccessor;
|
||||
private $choiceListFactory;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* ModelType constructor.
|
||||
*
|
||||
* @param PropertyAccessorInterface|null $propertyAccessor
|
||||
* @param PropertyAccessorInterface|null $propertyAccessor
|
||||
* @param ChoiceListFactoryInterface|null $choiceListFactory
|
||||
*/
|
||||
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
|
||||
public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null)
|
||||
{
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||
$this->choiceListFactory = $choiceListFactory ?: new PropertyAccessDecorator(
|
||||
new DefaultChoiceListFactory(),
|
||||
$propertyAccessor
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Creates the label for a choice.
|
||||
*
|
||||
* For backwards compatibility, objects are cast to strings by default.
|
||||
*
|
||||
* @param object $choice The object.
|
||||
*
|
||||
* @return string The string representation of the object.
|
||||
*
|
||||
* @internal This method is public to be usable as callback. It should not
|
||||
* be used in user code.
|
||||
*/
|
||||
public static function createChoiceLabel($choice)
|
||||
{
|
||||
return (string) $choice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the field name for a choice.
|
||||
*
|
||||
* This method is used to generate field names if the underlying object has
|
||||
* a single-column integer ID. In that case, the value of the field is
|
||||
* the ID of the object. That ID is also used as field name.
|
||||
*
|
||||
* @param object $choice The object.
|
||||
* @param int|string $key The choice key.
|
||||
* @param string $value The choice value. Corresponds to the object's
|
||||
* ID here.
|
||||
*
|
||||
* @return string The field name.
|
||||
*
|
||||
* @internal This method is public to be usable as callback. It should not
|
||||
* be used in user code.
|
||||
*/
|
||||
public static function createChoiceName($choice, $key, $value)
|
||||
{
|
||||
return str_replace('-', '_', (string) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($options['multiple']) {
|
||||
$builder->addViewTransformer(new CollectionToArrayTransformer(), true);
|
||||
$builder
|
||||
->addViewTransformer(new CollectionToArrayTransformer(), true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$propertyAccessor = $this->propertyAccessor;
|
||||
$choiceLoader = function (Options $options) {
|
||||
// Unless the choices are given explicitly, load them on demand
|
||||
if (null === $options['choices']) {
|
||||
|
||||
$choiceList = function (Options $options) use ($propertyAccessor) {
|
||||
return new ModelChoiceList(
|
||||
$options['class'],
|
||||
$options['property'],
|
||||
$options['choices'],
|
||||
$options['query'],
|
||||
$options['group_by'],
|
||||
$options['preferred_choices'],
|
||||
$propertyAccessor,
|
||||
$options['index_property']
|
||||
);
|
||||
$propelChoiceLoader = new PropelChoiceLoader(
|
||||
$this->choiceListFactory,
|
||||
$options['class'],
|
||||
$options['query'],
|
||||
$options['index_property']
|
||||
);
|
||||
|
||||
return $propelChoiceLoader;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
$resolver->setDefaults(array(
|
||||
'template' => 'choice',
|
||||
'multiple' => false,
|
||||
'expanded' => false,
|
||||
'class' => null,
|
||||
'property' => null,
|
||||
$choiceName = function (Options $options) {
|
||||
|
||||
/** @var ModelCriteria $query */
|
||||
$query = $options['query'];
|
||||
if ($options['index_property']) {
|
||||
$identifier = array($query->getTableMap()->getColumn($options['index_property']));
|
||||
} else {
|
||||
$identifier = $query->getTableMap()->getPrimaryKeys();
|
||||
}
|
||||
/** @var ColumnMap $firstIdentifier */
|
||||
$firstIdentifier = current($identifier);
|
||||
if (count($identifier) === 1 && $firstIdentifier->getPdoType() === \PDO::PARAM_INT) {
|
||||
return array(__CLASS__, 'createChoiceName');
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
$choiceValue = function (Options $options) {
|
||||
|
||||
/** @var ModelCriteria $query */
|
||||
$query = $options['query'];
|
||||
if ($options['index_property']) {
|
||||
$identifier = array($query->getTableMap()->getColumn($options['index_property']));
|
||||
} else {
|
||||
$identifier = $query->getTableMap()->getPrimaryKeys();
|
||||
}
|
||||
/** @var ColumnMap $firstIdentifier */
|
||||
$firstIdentifier = current($identifier);
|
||||
if (count($identifier) === 1 && in_array($firstIdentifier->getPdoType(), [\PDO::PARAM_BOOL, \PDO::PARAM_INT, \PDO::PARAM_STR])) {
|
||||
return function($object) use ($firstIdentifier) {
|
||||
return call_user_func([$object, 'get' . ucfirst($firstIdentifier->getPhpName())]);
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
$queryNormalizer = function (Options $options, $query) {
|
||||
if ($query === null) {
|
||||
$queryClass = $options['class'] . 'Query';
|
||||
if (!class_exists($queryClass)) {
|
||||
if (empty($options['class'])) {
|
||||
throw new MissingOptionsException('The "class" parameter is empty, you should provide the model class');
|
||||
}
|
||||
throw new InvalidOptionsException(
|
||||
sprintf(
|
||||
'The query class "%s" is not found, you should provide the FQCN of the model class',
|
||||
$queryClass
|
||||
)
|
||||
);
|
||||
}
|
||||
$query = new $queryClass();
|
||||
}
|
||||
return $query;
|
||||
};
|
||||
|
||||
$choiceLabelNormalizer = function (Options $options, $choiceLabel) {
|
||||
if ($choiceLabel === null) {
|
||||
if ($options['property'] == null) {
|
||||
$choiceLabel = array(__CLASS__, 'createChoiceLabel');
|
||||
} else {
|
||||
$valueProperty = $options['property'];
|
||||
/** @var ModelCriteria $query */
|
||||
$query = $options['query'];
|
||||
//var_dump($query->getTableMap());
|
||||
$getter = 'get' . ucfirst($query->getTableMap()->getColumn($valueProperty)->getPhpName());
|
||||
|
||||
$choiceLabel = function($choice) use ($getter) {
|
||||
return call_user_func([$choice, $getter]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return $choiceLabel;
|
||||
};
|
||||
|
||||
$resolver->setDefaults([
|
||||
'query' => null,
|
||||
'choices' => null,
|
||||
'choice_list' => $choiceList,
|
||||
'group_by' => null,
|
||||
'by_reference' => false,
|
||||
'index_property' => null,
|
||||
));
|
||||
'property' => null,
|
||||
'choices' => null,
|
||||
'choices_as_values' => true,
|
||||
'choice_loader' => $choiceLoader,
|
||||
'choice_label' => null,
|
||||
'choice_name' => $choiceName,
|
||||
'choice_value' => $choiceValue,
|
||||
'choice_translation_domain' => false,
|
||||
'by_reference' => false,
|
||||
]);
|
||||
|
||||
$resolver->setRequired(array('class'));
|
||||
$resolver->setNormalizer('query', $queryNormalizer);
|
||||
$resolver->setNormalizer('choice_label', $choiceLabelNormalizer);
|
||||
$resolver->setAllowedTypes('query', ['null', 'Propel\Runtime\ActiveQuery\ModelCriteria']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return 'choice';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'model';
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return 'Symfony\Component\Form\Extension\Core\Type\ChoiceType';
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue