Skip to content

Commit e10bb77

Browse files
authored
Merge pull request propelorm#465 from jaugustin/1.6
[1.6] make form type work with sf 3.x
2 parents 7f8ffd7 + 6fe96ad commit e10bb77

19 files changed

Lines changed: 712 additions & 1080 deletions

Form/ChoiceList/ModelChoiceList.php

Lines changed: 0 additions & 512 deletions
This file was deleted.
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the PropelBundle package.
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*
8+
* @license MIT License
9+
*/
10+
11+
namespace Propel\Bundle\PropelBundle\Form\ChoiceList;
12+
13+
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
14+
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
15+
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
16+
17+
/**
18+
* @author William Durand <william.durand1@gmail.com>
19+
* @author Toni Uebernickel <tuebernickel@gmail.com>
20+
* @author Moritz Schroeder <moritz.schroeder@molabs.de>
21+
*/
22+
class PropelChoiceLoader implements ChoiceLoaderInterface
23+
{
24+
/**
25+
* @var string
26+
*/
27+
protected $class;
28+
29+
/**
30+
* @var \ModelCriteria
31+
*/
32+
protected $query;
33+
34+
/**
35+
* The fields of which the identifier of the underlying class consists
36+
*
37+
* This property should only be accessed through identifier.
38+
*
39+
* @var array
40+
*/
41+
protected $identifier = array();
42+
43+
/**
44+
* Whether to use the identifier for index generation.
45+
*
46+
* @var bool
47+
*/
48+
protected $identifierAsIndex = false;
49+
50+
/**
51+
* @var ChoiceListInterface
52+
*/
53+
protected $choiceList;
54+
55+
/**
56+
* PropelChoiceListLoader constructor.
57+
*
58+
* @param string $class
59+
* @param \ModelCriteria $queryObject
60+
* @param string $useAsIdentifier
61+
*/
62+
public function __construct($class, \ModelCriteria $queryObject, $useAsIdentifier = null)
63+
{
64+
$this->class = $class;
65+
$this->query = $queryObject;
66+
if ($useAsIdentifier) {
67+
$this->identifier = array($this->query->getTableMap()->getColumn($useAsIdentifier));
68+
} else {
69+
$this->identifier = $this->query->getTableMap()->getPrimaryKeys();
70+
}
71+
if (1 === count($this->identifier) && $this->isScalar(current($this->identifier))) {
72+
$this->identifierAsIndex = true;
73+
}
74+
}
75+
76+
/**
77+
* {@inheritdoc}
78+
*/
79+
public function loadChoiceList($value = null)
80+
{
81+
if ($this->choiceList) {
82+
return $this->choiceList;
83+
}
84+
85+
$models = iterator_to_array($this->query->find());
86+
87+
return $this->choiceList = new ArrayChoiceList($models, $value);
88+
}
89+
90+
/**
91+
* {@inheritdoc}
92+
*/
93+
public function loadChoicesForValues(array $values, $value = null)
94+
{
95+
// Performance optimization
96+
if (empty($values)) {
97+
return array();
98+
}
99+
100+
$optimize = null === $value;
101+
102+
// Optimize performance in case we have a single-field identifier
103+
if ($optimize && !$this->choiceList && $this->identifierAsIndex && current($this->identifier) instanceof \ColumnMap) {
104+
$phpName = current($this->identifier)->getPhpName();
105+
$query = clone $this->query;
106+
$unorderedObjects = $query->filterBy($phpName, $values, \Criteria::IN)->find();
107+
$objectsById = array();
108+
$objects = array();
109+
110+
// Maintain order and indices from the given $values
111+
foreach ($unorderedObjects as $object) {
112+
$objectsById[(string) current($this->getIdentifierValues($object))] = $object;
113+
}
114+
115+
foreach ($values as $i => $id) {
116+
if (isset($objectsById[$id])) {
117+
$objects[$i] = $objectsById[$id];
118+
}
119+
}
120+
121+
return $objects;
122+
}
123+
124+
return $this->loadChoiceList($value)->getChoicesForValues($values);
125+
}
126+
127+
/**
128+
* {@inheritdoc}
129+
*/
130+
public function loadValuesForChoices(array $choices, $value = null)
131+
{
132+
// Performance optimization
133+
if (empty($choices)) {
134+
return array();
135+
}
136+
137+
$optimize = null === $value;
138+
139+
if ($optimize && !$this->choiceList && $this->identifierAsIndex) {
140+
$values = array();
141+
142+
// Maintain order and indices of the given objects
143+
foreach ($choices as $i => $object) {
144+
if ($object instanceof $this->class) {
145+
// Make sure to convert to the right format
146+
$values[$i] = (string) current($this->getIdentifierValues($object));
147+
}
148+
}
149+
150+
return $values;
151+
}
152+
153+
return $this->loadChoiceList($value)->getValuesForChoices($choices);
154+
}
155+
156+
/**
157+
* Whether this column contains scalar values (to be used as indices).
158+
*
159+
* @param \ColumnMap $column
160+
*
161+
* @return bool
162+
*/
163+
private function isScalar(\ColumnMap $column)
164+
{
165+
return in_array(
166+
$column->getPdoType(),
167+
array(
168+
\PDO::PARAM_BOOL,
169+
\PDO::PARAM_INT,
170+
\PDO::PARAM_STR,
171+
)
172+
);
173+
}
174+
175+
/**
176+
* Returns the values of the identifier fields of a model.
177+
*
178+
* Propel must know about this model, that is, the model must already
179+
* be persisted or added to the idmodel map before. Otherwise an
180+
* exception is thrown.
181+
*
182+
* @param object $model The model for which to get the identifier
183+
*
184+
* @return array
185+
*/
186+
private function getIdentifierValues($model)
187+
{
188+
if (!$model instanceof $this->class) {
189+
return array();
190+
}
191+
192+
if (1 === count($this->identifier) && current($this->identifier) instanceof \ColumnMap) {
193+
$phpName = current($this->identifier)->getPhpName();
194+
if (method_exists($model, 'get' . $phpName)) {
195+
return array($model->{'get' . $phpName}());
196+
}
197+
}
198+
199+
if ($model instanceof \BaseObject) {
200+
return array($model->getPrimaryKey());
201+
}
202+
203+
return $model->getPrimaryKeys();
204+
}
205+
206+
}

Form/EventListener/TranslationFormListener.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace Propel\Bundle\PropelBundle\Form\EventListener;
1212

1313
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
14+
use Symfony\Component\Form\Extension\Core\Type\TextType;
1415
use Symfony\Component\Form\FormEvent;
1516
use Symfony\Component\Form\FormEvents;
1617

@@ -56,7 +57,7 @@ public function preSetData(FormEvent $event)
5657
$options = array();
5758
}
5859

59-
$type = 'text';
60+
$type = TextType::class;
6061
if (array_key_exists('type', $options)) {
6162
$type = $options['type'];
6263
}

Form/PropelTypeGuesser.php

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111

1212
namespace Propel\Bundle\PropelBundle\Form;
1313

14+
use Propel\Bundle\PropelBundle\Form\Type\ModelType;
15+
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
16+
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
17+
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
18+
use Symfony\Component\Form\Extension\Core\Type\DateType;
19+
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
20+
use Symfony\Component\Form\Extension\Core\Type\NumberType;
21+
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
22+
use Symfony\Component\Form\Extension\Core\Type\TextType;
23+
use Symfony\Component\Form\Extension\Core\Type\TimeType;
1424
use Symfony\Component\Form\FormTypeGuesserInterface;
1525
use Symfony\Component\Form\Guess\Guess;
1626
use Symfony\Component\Form\Guess\TypeGuess;
@@ -31,27 +41,27 @@ class PropelTypeGuesser implements FormTypeGuesserInterface
3141
public function guessType($class, $property)
3242
{
3343
if (!$table = $this->getTable($class)) {
34-
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
44+
return new TypeGuess(TextType::class, array(), Guess::LOW_CONFIDENCE);
3545
}
3646

3747
foreach ($table->getRelations() as $relation) {
3848
if ($relation->getType() === \RelationMap::MANY_TO_ONE) {
3949
if (strtolower($property) === strtolower($relation->getName())) {
40-
return new TypeGuess('model', array(
50+
return new TypeGuess(ModelType::class, array(
4151
'class' => $relation->getForeignTable()->getClassName(),
4252
'multiple' => false,
4353
), Guess::HIGH_CONFIDENCE);
4454
}
4555
} elseif ($relation->getType() === \RelationMap::ONE_TO_MANY) {
4656
if (strtolower($property) === strtolower($relation->getPluralName())) {
47-
return new TypeGuess('model', array(
57+
return new TypeGuess(ModelType::class, array(
4858
'class' => $relation->getForeignTable()->getClassName(),
4959
'multiple' => true,
5060
), Guess::HIGH_CONFIDENCE);
5161
}
5262
} elseif ($relation->getType() === \RelationMap::MANY_TO_MANY) {
5363
if (strtolower($property) == strtolower($relation->getPluralName())) {
54-
return new TypeGuess('model', array(
64+
return new TypeGuess(ModelType::class, array(
5565
'class' => $relation->getLocalTable()->getClassName(),
5666
'multiple' => true,
5767
), Guess::HIGH_CONFIDENCE);
@@ -60,50 +70,50 @@ public function guessType($class, $property)
6070
}
6171

6272
if (!$column = $this->getColumn($class, $property)) {
63-
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
73+
return new TypeGuess(TextType::class, array(), Guess::LOW_CONFIDENCE);
6474
}
6575

6676
switch ($column->getType()) {
6777
case \PropelColumnTypes::BOOLEAN:
6878
case \PropelColumnTypes::BOOLEAN_EMU:
69-
return new TypeGuess('checkbox', array(), Guess::HIGH_CONFIDENCE);
79+
return new TypeGuess(CheckboxType::class, array(), Guess::HIGH_CONFIDENCE);
7080
case \PropelColumnTypes::TIMESTAMP:
7181
case \PropelColumnTypes::BU_TIMESTAMP:
72-
return new TypeGuess('datetime', array(), Guess::HIGH_CONFIDENCE);
82+
return new TypeGuess(DateTimeType::class, array(), Guess::HIGH_CONFIDENCE);
7383
case \PropelColumnTypes::DATE:
7484
case \PropelColumnTypes::BU_DATE:
75-
return new TypeGuess('date', array(), Guess::HIGH_CONFIDENCE);
85+
return new TypeGuess(DateType::class, array(), Guess::HIGH_CONFIDENCE);
7686
case \PropelColumnTypes::TIME:
77-
return new TypeGuess('time', array(), Guess::HIGH_CONFIDENCE);
87+
return new TypeGuess(TimeType::class, array(), Guess::HIGH_CONFIDENCE);
7888
case \PropelColumnTypes::FLOAT:
7989
case \PropelColumnTypes::REAL:
8090
case \PropelColumnTypes::DOUBLE:
8191
case \PropelColumnTypes::DECIMAL:
82-
return new TypeGuess('number', array(), Guess::MEDIUM_CONFIDENCE);
92+
return new TypeGuess(NumberType::class, array(), Guess::MEDIUM_CONFIDENCE);
8393
case \PropelColumnTypes::TINYINT:
8494
case \PropelColumnTypes::SMALLINT:
8595
case \PropelColumnTypes::INTEGER:
8696
case \PropelColumnTypes::BIGINT:
8797
case \PropelColumnTypes::NUMERIC:
88-
return new TypeGuess('integer', array(), Guess::MEDIUM_CONFIDENCE);
98+
return new TypeGuess(IntegerType::class, array(), Guess::MEDIUM_CONFIDENCE);
8999
case \PropelColumnTypes::ENUM:
90100
case \PropelColumnTypes::CHAR:
91101
if ($column->getValueSet()) {
92102
//check if this is mysql enum
93103
$choices = $column->getValueSet();
94104
$labels = array_map('ucfirst', $choices);
95105

96-
return new TypeGuess('choice', array('choices' => array_combine($choices, $labels)), Guess::MEDIUM_CONFIDENCE);
106+
return new TypeGuess(ChoiceType::class, array('choices' => array_combine($choices, $labels)), Guess::MEDIUM_CONFIDENCE);
97107
}
98108
case \PropelColumnTypes::VARCHAR:
99-
return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE);
109+
return new TypeGuess(TextType::class, array(), Guess::MEDIUM_CONFIDENCE);
100110
case \PropelColumnTypes::LONGVARCHAR:
101111
case \PropelColumnTypes::BLOB:
102112
case \PropelColumnTypes::CLOB:
103113
case \PropelColumnTypes::CLOB_EMU:
104-
return new TypeGuess('textarea', array(), Guess::MEDIUM_CONFIDENCE);
114+
return new TypeGuess(TextareaType::class, array(), Guess::MEDIUM_CONFIDENCE);
105115
default:
106-
return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE);
116+
return new TypeGuess(TextType::class, array(), Guess::LOW_CONFIDENCE);
107117
}
108118
}
109119

0 commit comments

Comments
 (0)