Permalink
Browse files

ENHANCEMENT Allowing array values in ListboxField->setValue(), serial…

…ising into comma-separated list of values (AIR-35)
  • Loading branch information...
1 parent 007eb25 commit 4d31ac65a04c29bd1e4a6a7c818ecd9bc1c4c8ba @chillu chillu committed Aug 29, 2011
Showing with 204 additions and 1 deletion.
  1. +1 −1 forms/DropdownField.php
  2. +58 −0 forms/ListboxField.php
  3. +145 −0 tests/forms/ListboxFieldTest.php
View
2 forms/DropdownField.php
@@ -122,7 +122,7 @@ class DropdownField extends FormField {
* Argument is deprecated in 2.3, please use {@link setHasEmptyDefault()} and {@link setEmptyString()} instead.
*/
function __construct($name, $title = null, $source = array(), $value = "", $form = null, $emptyString = null) {
- $this->source = $source;
+ $this->setSource($source);
if($emptyString) $this->setHasEmptyDefault(true);
if(is_string($emptyString)) $this->setEmptyString($emptyString);
View
58 forms/ListboxField.php
@@ -116,5 +116,63 @@ function setMultiple($bool) {
$this->multiple = $bool;
}
+ function setSource($source) {
+ if($source) {
+ $hasCommas = array_filter(array_keys($source), create_function('$key', 'return strpos($key, ",") !== FALSE;'));
+ if($hasCommas) {
+ throw new InvalidArgumentException('No commas allowed in $source keys');
+ }
+ }
+
+ parent::setSource($source);
+ }
+
+ /**
+ * @return String
+ */
+ function dataValue() {
+ if($this->value && $this->multiple && is_array($this->value)) {
+ return implode(',', $this->value);
+ } else {
+ return parent::dataValue();
+ }
+ }
+
+ function setValue($val) {
+ if($val) {
+ if(!$this->multiple && is_array($val)) {
+ throw new InvalidArgumentException('No array values allowed with multiple=false');
+ }
+
+ if($this->multiple) {
+ $parts = (is_array($val)) ? $val : preg_split("/ *, */", trim($val));
+ if(ArrayLib::is_associative($parts)) {
+ throw new InvalidArgumentException('No associative arrays allowed multiple=true');
+ }
+
+ if($diff = array_diff($parts, array_keys($this->source))) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid keys "%s" in value array for multiple=true',
+ Convert::raw2xml(implode(',', $diff))
+ ));
+ }
+
+ parent::setValue($parts);
+ } else {
+ if(!in_array($val, array_keys($this->source))) {
+ throw new InvalidArgumentException(sprintf(
+ 'Invalid value "%s" for multiple=true',
+ Convert::raw2xml($val)
+ ));
+ }
+
+ parent::setValue($val);
+ }
+ } else {
+ parent::setValue($val);
+ }
+
+ }
+
}
?>
View
145 tests/forms/ListboxFieldTest.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * @package sapphire
+ * @subpackage tests
+ */
+
+class ListboxFieldTest extends SapphireTest {
+
+ protected $extraDataObjects = array('ListboxFieldTest_DataObject');
+
+ function testSaveIntoNullValueWithMultipleOff() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = true;
+
+ $obj = new ListboxFieldTest_DataObject();
+ $field->setValue('a');
+ $field->saveInto($obj);
+ $field->setValue(null);
+ $field->saveInto($obj);
+ $this->assertNull($obj->Choices);
+ }
+
+ function testSaveIntoNullValueWithMultipleOn() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = true;
+
+ $obj = new ListboxFieldTest_DataObject();
+ $field->setValue('a,c');
+ $field->saveInto($obj);
+ $field->setValue('');
+ $field->saveInto($obj);
+ $this->assertEquals('', $obj->Choices);
+ }
+
+ function testSaveInto() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = false;
+
+ $obj = new ListboxFieldTest_DataObject();
+ $field->setValue('a');
+ $field->saveInto($obj);
+ $this->assertEquals('a', $obj->Choices);
+ }
+
+ function testSaveIntoMultiple() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = true;
+
+ // As array
+ $obj1 = new ListboxFieldTest_DataObject();
+ $field->setValue(array('a', 'c'));
+ $field->saveInto($obj1);
+ $this->assertEquals('a,c', $obj1->Choices);
+
+ // As string
+ $obj2 = new ListboxFieldTest_DataObject();
+ $field->setValue('a,c');
+ $field->saveInto($obj2);
+ $this->assertEquals('a,c', $obj2->Choices);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testSetValueFailsOnArrayIfMultipleIsOff() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = false;
+
+ // As array (type error)
+ $failsOnArray = false;
+ $obj = new ListboxFieldTest_DataObject();
+ $field->setValue(array('a', 'c'));
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testSetValueFailsOnStringIfChoiceInvalidAndMultipleIsOff() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = false;
+
+ // As string (invalid choice as comma is regarded literal)
+ $obj = new ListboxFieldTest_DataObject();
+ $field->setValue('invalid');
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testSetValueFailsOnInvalidArrayKeyIfChoiceInvalidAndMultipleIsOn() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = true;
+
+ $obj = new ListboxFieldTest_DataObject();
+ $field->setValue(array('a', 'invalid'));
+ }
+
+ function testFieldRenderingMultipleOff() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = true;
+ $field->setValue('a');
+ $parser = new CSSContentParser($field->Field());
+ $optEls = $parser->getBySelector('option');
+ $this->assertEquals(3, count($optEls));
+ $this->assertEquals('selected', (string)$optEls[0]['selected']);
+ $this->assertEquals('', (string)$optEls[1]['selected']);
+ $this->assertEquals('', (string)$optEls[2]['selected']);
+ }
+
+ function testFieldRenderingMultipleOn() {
+ $choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ $field->multiple = true;
+ $field->setValue('a,c');
+ $parser = new CSSContentParser($field->Field());
+ $optEls = $parser->getBySelector('option');
+ $this->assertEquals(3, count($optEls));
+ $this->assertEquals('selected', (string)$optEls[0]['selected']);
+ $this->assertEquals('', (string)$optEls[1]['selected']);
+ $this->assertEquals('selected', (string)$optEls[2]['selected']);
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ function testCommasInSourceKeys() {
+ $choices = array('a' => 'a value', 'b,with,comma' => 'b value,with,comma',);
+ $field = new ListboxField('Choices', 'Choices', $choices);
+ }
+
+}
+
+class ListboxFieldTest_DataObject extends DataObject implements TestOnly {
+ static $db = array(
+ 'Choices' => 'Text'
+ );
+}

0 comments on commit 4d31ac6

Please sign in to comment.