From 1ff6142881f45de2d24642c58fab082cdb2f439c Mon Sep 17 00:00:00 2001 From: Miha Vrhovnik Date: Wed, 28 Mar 2012 08:01:54 +0200 Subject: [PATCH 1/2] label path in ObjectChoiceList can also be callable --- .../Core/ChoiceList/ObjectChoiceList.php | 23 +++++++++++++++---- .../Core/ChoiceList/ObjectChoiceListTest.php | 20 ++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php index daf13efcd353f..ed63d859771a3 100644 --- a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -71,9 +71,11 @@ class ObjectChoiceList extends ChoiceList * key pointing to the nested array. * @param string $labelPath A property path pointing to the property used * for the choice labels. The value is obtained - * by calling the getter on the object. If the - * path is NULL, the object's __toString() method - * is used instead. + * by calling the getter on the object. You can + * also pass any callable. When callable will be + * executed it wil get the choice parameter passed. + * If the path is NULL, the object's __toString() + * method is used instead. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. * @param string $groupPath A property path pointing to the property used @@ -88,7 +90,14 @@ class ObjectChoiceList extends ChoiceList */ public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, $indexPath = null) { - $this->labelPath = $labelPath ? new PropertyPath($labelPath) : null; + if (is_scalar($labelPath)) { + $this->labelPath = new PropertyPath($labelPath); + } elseif (is_callable($labelPath)) { + $this->labelPath = $labelPath; + } else { + $this->labelPath = null; + } + $this->groupPath = $groupPath ? new PropertyPath($groupPath) : null; $this->valuePath = $valuePath ? new PropertyPath($valuePath) : null; $this->indexPath = $indexPath ? new PropertyPath($indexPath) : null; @@ -191,12 +200,16 @@ protected function createValue($choice) private function extractLabels($choices, array &$labels) { + $callable = is_callable($this->labelPath) ? $this->labelPath : false; + foreach ($choices as $i => $choice) { if (is_array($choice) || $choice instanceof \Traversable) { $labels[$i] = array(); $this->extractLabels($choice, $labels[$i]); - } elseif ($this->labelPath) { + } elseif ($this->labelPath instanceof PropertyPath) { $labels[$i] = $this->labelPath->getValue($choice); + } elseif (is_callable($this->labelPath)) { + $labels[$i] = $callable($choice); } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 0834578ac8b7b..aeda0f9f8ab86 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -45,10 +45,10 @@ protected function setUp() { parent::setUp(); - $this->obj1 = (object) array('name' => 'A'); - $this->obj2 = (object) array('name' => 'B'); - $this->obj3 = (object) array('name' => 'C'); - $this->obj4 = (object) array('name' => 'D'); + $this->obj1 = (object) array('name' => 'A', 'number' => 1); + $this->obj2 = (object) array('name' => 'B', 'number' => 2); + $this->obj3 = (object) array('name' => 'C', 'number' => 3); + $this->obj4 = (object) array('name' => 'D', 'number' => 4); $this->list = new ObjectChoiceList( array( @@ -228,4 +228,16 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); } + + public function testCallableArray() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + function ($choice) { + return $choice->name . $choice->number; + } + ); + + $this->assertEquals(array(0 => new ChoiceView('0', 'A1'), 1 => new ChoiceView('1', 'B2'), 2 => new ChoiceView('2', 'C3'), 3 => new ChoiceView('3', 'D4')), $this->list->getRemainingViews()); + } } From c012b8b8c4f07883e9fc0a41f3ec28b7d672ff1e Mon Sep 17 00:00:00 2001 From: Miha Vrhovnik Date: Wed, 28 Mar 2012 12:37:46 +0200 Subject: [PATCH 2/2] fixed typo, $callable => call_user_func as it works for any callable --- .../Form/Extension/Core/ChoiceList/ObjectChoiceList.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php index ed63d859771a3..ab1fd34d81f93 100644 --- a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -73,7 +73,7 @@ class ObjectChoiceList extends ChoiceList * for the choice labels. The value is obtained * by calling the getter on the object. You can * also pass any callable. When callable will be - * executed it wil get the choice parameter passed. + * executed it will get the choice parameter passed. * If the path is NULL, the object's __toString() * method is used instead. * @param array $preferredChoices A flat array of choices that should be @@ -200,8 +200,6 @@ protected function createValue($choice) private function extractLabels($choices, array &$labels) { - $callable = is_callable($this->labelPath) ? $this->labelPath : false; - foreach ($choices as $i => $choice) { if (is_array($choice) || $choice instanceof \Traversable) { $labels[$i] = array(); @@ -209,7 +207,7 @@ private function extractLabels($choices, array &$labels) } elseif ($this->labelPath instanceof PropertyPath) { $labels[$i] = $this->labelPath->getValue($choice); } elseif (is_callable($this->labelPath)) { - $labels[$i] = $callable($choice); + $labels[$i] = call_user_func($this->labelPath, $choice); } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else {