diff --git a/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php b/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php index 4176777b37..0a3eab0903 100644 --- a/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php +++ b/src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php @@ -11,8 +11,10 @@ namespace Symfony\Bridge\Propel1\Form\ChoiceList; +use \ModelCriteria; use \BaseObject; use \Persistent; + use Symfony\Component\Form\Exception\FormException; use Symfony\Component\Form\Exception\StringCastException; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; @@ -21,6 +23,7 @@ use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; * Widely inspirated by the EntityChoiceList. * * @author William Durand + * @author Toni Uebernickel */ class ModelChoiceList extends ObjectChoiceList { @@ -31,28 +34,44 @@ class ModelChoiceList extends ObjectChoiceList * * @var array */ - private $identifier = array(); + protected $identifier = array(); /** - * Query + * The query to retrieve the choices of this list. + * + * @var ModelCriteria */ - private $query = null; + protected $query; + + /** + * The query to retrieve the preferred choices for this list. + * + * @var ModelCriteria + */ + protected $preferredQuery; /** * Whether the model objects have already been loaded. * * @var Boolean */ - private $loaded = false; + protected $loaded = false; /** - * @param string $class - * @param string $labelPath - * @param array $choices - * @param \ModelCriteria $queryObject - * @param string $groupPath + * Constructor. + * + * @see Symfony\Bridge\Propel1\Form\Type\ModelType How to use the preferred choices. + * + * @param string $class The FQCN of the model class to be loaded. + * @param string $labelPath A property path pointing to the property used for the choice labels. + * @param array $choices An optional array to use, rather than fetching the models. + * @param ModelCriteria $queryObject The query to use retrieving model data from database. + * @param string $groupPath A property path pointing to the property used to group the choices. + * @param array|ModelCriteria $preferred The preferred items of this choice. + * Either an array if $choices is given, + * or a ModelCriteria to be merged with the $queryObject. */ - public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null) + public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null, $preferred = array()) { $this->class = $class; @@ -63,13 +82,18 @@ class ModelChoiceList extends ObjectChoiceList $this->query = $queryObject ?: $query; $this->loaded = is_array($choices) || $choices instanceof \Traversable; + if ($preferred instanceof ModelCriteria) { + $this->preferredQuery = $preferred->mergeWith($this->query); + } + if (!$this->loaded) { // Make sure the constraints of the parent constructor are // fulfilled $choices = array(); + $preferred = array(); } - parent::__construct($choices, $labelPath, array(), $groupPath); + parent::__construct($choices, $labelPath, $preferred, $groupPath); } /** @@ -317,10 +341,14 @@ class ModelChoiceList extends ObjectChoiceList { $models = (array) $this->query->find(); + $preferred = array(); + if ($this->preferredQuery instanceof ModelCriteria) { + $preferred = (array) $this->preferredQuery->find(); + } + try { // The second parameter $labels is ignored by ObjectChoiceList - // The third parameter $preferredChoices is currently not supported - parent::initialize($models, array(), array()); + parent::initialize($models, array(), $preferred); } catch (StringCastException $e) { throw new StringCastException(str_replace('argument $labelPath', 'option "property"', $e->getMessage()), null, $e); } diff --git a/src/Symfony/Bridge/Propel1/Form/Type/ModelType.php b/src/Symfony/Bridge/Propel1/Form/Type/ModelType.php index 820153c68d..faf5f25f1c 100644 --- a/src/Symfony/Bridge/Propel1/Form/Type/ModelType.php +++ b/src/Symfony/Bridge/Propel1/Form/Type/ModelType.php @@ -22,6 +22,29 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface; * ModelType class. * * @author William Durand + * @author Toni Uebernickel + * + * Example using the preferred_choices option. + * + * + * public function buildForm(FormBuilderInterface $builder, array $options) + * { + * $builder + * ->add('product', 'model', array( + * 'class' => 'Model\Product', + * 'query' => ProductQuery::create() + * ->filterIsActive(true) + * ->useI18nQuery($options['locale']) + * ->orderByName() + * ->endUse() + * , + * 'preferred_choices' => ProductQuery::create() + * ->filterByIsTopProduct(true) + * , + * )) + * ; + * } + * */ class ModelType extends AbstractType { @@ -40,7 +63,8 @@ class ModelType extends AbstractType $options['property'], $options['choices'], $options['query'], - $options['group_by'] + $options['group_by'], + $options['preferred_choices'] ); }; diff --git a/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php b/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php index 68f690db95..6675eac727 100644 --- a/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php +++ b/src/Symfony/Bridge/Propel1/Tests/Form/ChoiceList/ModelChoiceListTest.php @@ -70,6 +70,29 @@ class ModelChoiceListTest extends Propel1TestCase $this->assertSame(array(1 => $item1, 2 => $item2), $choiceList->getChoices()); } + public function testFlattenedPreferredChoices() + { + $item1 = new Item(1, 'Foo'); + $item2 = new Item(2, 'Bar'); + + $choiceList = new ModelChoiceList( + self::ITEM_CLASS, + 'value', + array( + $item1, + $item2, + ), + null, + null, + array( + $item1 + ) + ); + + $this->assertSame(array(1 => $item1, 2 => $item2), $choiceList->getChoices()); + $this->assertEquals(array(1 => new ChoiceView($item1, '1', 'Foo')), $choiceList->getPreferredViews()); + } + public function testNestedChoices() { $item1 = new Item(1, 'Foo');