fix symfony 2.8 deprecation warnings

This commit is contained in:
Jeffrey Wong 2016-06-10 12:04:01 -07:00 committed by Toni Uebernickel
parent 70807641c7
commit 0b31960534
No known key found for this signature in database
GPG key ID: BE780866F6035C7A
3 changed files with 411 additions and 44 deletions

View 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();
}
}

View file

@ -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(),
);

View file

@ -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';
}
}