Skip to content
This repository
Browse code

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

…ising into comma-separated list of values (AIR-35)
  • Loading branch information...
commit 4d31ac65a04c29bd1e4a6a7c818ecd9bc1c4c8ba 1 parent 007eb25
Ingo Schommer authored August 29, 2011
2  forms/DropdownField.php
@@ -122,7 +122,7 @@ class DropdownField extends FormField {
122 122
 	 *  Argument is deprecated in 2.3, please use {@link setHasEmptyDefault()} and {@link setEmptyString()} instead.
123 123
 	 */
124 124
 	function __construct($name, $title = null, $source = array(), $value = "", $form = null, $emptyString = null) {
125  
-		$this->source = $source;
  125
+		$this->setSource($source);
126 126
 		
127 127
 		if($emptyString) $this->setHasEmptyDefault(true);
128 128
 		if(is_string($emptyString)) $this->setEmptyString($emptyString);
58  forms/ListboxField.php
@@ -116,5 +116,63 @@ function setMultiple($bool) {
116 116
 		$this->multiple = $bool;
117 117
 	}
118 118
 	
  119
+	function setSource($source) {
  120
+		if($source) {
  121
+			$hasCommas = array_filter(array_keys($source), create_function('$key', 'return strpos($key, ",") !== FALSE;'));
  122
+			if($hasCommas) {
  123
+				throw new InvalidArgumentException('No commas allowed in $source keys');
  124
+			}
  125
+		}
  126
+		
  127
+		parent::setSource($source);
  128
+	}
  129
+	
  130
+	/**
  131
+	 * @return String
  132
+	 */
  133
+	function dataValue() {
  134
+		if($this->value && $this->multiple && is_array($this->value)) {
  135
+			return implode(',', $this->value);
  136
+		} else {
  137
+			return parent::dataValue();
  138
+		}
  139
+	}
  140
+	
  141
+	function setValue($val) {
  142
+		if($val) {
  143
+			if(!$this->multiple && is_array($val)) {
  144
+				throw new InvalidArgumentException('No array values allowed with multiple=false');
  145
+			}
  146
+
  147
+			if($this->multiple) {
  148
+				$parts = (is_array($val)) ? $val : preg_split("/ *, */", trim($val));
  149
+				if(ArrayLib::is_associative($parts)) {
  150
+					throw new InvalidArgumentException('No associative arrays allowed multiple=true');
  151
+				}
  152
+
  153
+				if($diff = array_diff($parts, array_keys($this->source))) {
  154
+					throw new InvalidArgumentException(sprintf(
  155
+						'Invalid keys "%s" in value array for multiple=true', 
  156
+						Convert::raw2xml(implode(',', $diff))
  157
+					));
  158
+				}
  159
+
  160
+				parent::setValue($parts);
  161
+			} else {
  162
+				if(!in_array($val, array_keys($this->source))) {
  163
+					throw new InvalidArgumentException(sprintf(
  164
+						'Invalid value "%s" for multiple=true', 
  165
+						Convert::raw2xml($val)
  166
+					));
  167
+				}
  168
+
  169
+				parent::setValue($val);
  170
+			}
  171
+		} else {
  172
+			parent::setValue($val);
  173
+		}
  174
+		
  175
+	}
  176
+	
119 177
 }
120 178
 ?>
145  tests/forms/ListboxFieldTest.php
... ...
@@ -0,0 +1,145 @@
  1
+<?php
  2
+/**
  3
+ * @package sapphire
  4
+ * @subpackage tests
  5
+ */
  6
+
  7
+class ListboxFieldTest extends SapphireTest {
  8
+	
  9
+	protected $extraDataObjects = array('ListboxFieldTest_DataObject');
  10
+	
  11
+	function testSaveIntoNullValueWithMultipleOff() {
  12
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  13
+		$field = new ListboxField('Choices', 'Choices', $choices);
  14
+		$field->multiple = true;
  15
+		
  16
+		$obj = new ListboxFieldTest_DataObject();
  17
+		$field->setValue('a');
  18
+		$field->saveInto($obj);
  19
+		$field->setValue(null);
  20
+		$field->saveInto($obj);
  21
+		$this->assertNull($obj->Choices);
  22
+	}
  23
+	
  24
+	function testSaveIntoNullValueWithMultipleOn() {
  25
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  26
+		$field = new ListboxField('Choices', 'Choices', $choices);
  27
+		$field->multiple = true;
  28
+		
  29
+		$obj = new ListboxFieldTest_DataObject();
  30
+		$field->setValue('a,c');
  31
+		$field->saveInto($obj);
  32
+		$field->setValue('');
  33
+		$field->saveInto($obj);
  34
+		$this->assertEquals('', $obj->Choices);
  35
+	}
  36
+	
  37
+	function testSaveInto() {
  38
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  39
+		$field = new ListboxField('Choices', 'Choices', $choices);
  40
+		$field->multiple = false;
  41
+		
  42
+		$obj = new ListboxFieldTest_DataObject();
  43
+		$field->setValue('a');
  44
+		$field->saveInto($obj);
  45
+		$this->assertEquals('a', $obj->Choices);
  46
+	}
  47
+	
  48
+	function testSaveIntoMultiple() {
  49
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  50
+		$field = new ListboxField('Choices', 'Choices', $choices);
  51
+		$field->multiple = true;
  52
+		
  53
+		// As array
  54
+		$obj1 = new ListboxFieldTest_DataObject();
  55
+		$field->setValue(array('a', 'c'));
  56
+		$field->saveInto($obj1);
  57
+		$this->assertEquals('a,c', $obj1->Choices);
  58
+		
  59
+		// As string
  60
+		$obj2 = new ListboxFieldTest_DataObject();
  61
+		$field->setValue('a,c');
  62
+		$field->saveInto($obj2);
  63
+		$this->assertEquals('a,c', $obj2->Choices);
  64
+	}
  65
+	
  66
+	/**
  67
+	 * @expectedException InvalidArgumentException
  68
+	 */
  69
+	function testSetValueFailsOnArrayIfMultipleIsOff() {
  70
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  71
+		$field = new ListboxField('Choices', 'Choices', $choices);
  72
+		$field->multiple = false;
  73
+		
  74
+		// As array (type error)
  75
+		$failsOnArray = false;
  76
+		$obj = new ListboxFieldTest_DataObject();
  77
+		$field->setValue(array('a', 'c'));
  78
+	}
  79
+	
  80
+	/**
  81
+	 * @expectedException InvalidArgumentException
  82
+	 */
  83
+	function testSetValueFailsOnStringIfChoiceInvalidAndMultipleIsOff() {
  84
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  85
+		$field = new ListboxField('Choices', 'Choices', $choices);
  86
+		$field->multiple = false;
  87
+		
  88
+		// As string (invalid choice as comma is regarded literal)
  89
+		$obj = new ListboxFieldTest_DataObject();
  90
+		$field->setValue('invalid');
  91
+	}
  92
+	
  93
+	/**
  94
+	 * @expectedException InvalidArgumentException
  95
+	 */
  96
+	function testSetValueFailsOnInvalidArrayKeyIfChoiceInvalidAndMultipleIsOn() {
  97
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  98
+		$field = new ListboxField('Choices', 'Choices', $choices);
  99
+		$field->multiple = true;
  100
+		
  101
+		$obj = new ListboxFieldTest_DataObject();
  102
+		$field->setValue(array('a', 'invalid'));
  103
+	}
  104
+	
  105
+	function testFieldRenderingMultipleOff() {
  106
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  107
+		$field = new ListboxField('Choices', 'Choices', $choices);
  108
+		$field->multiple = true;
  109
+		$field->setValue('a');
  110
+		$parser = new CSSContentParser($field->Field());
  111
+		$optEls = $parser->getBySelector('option');
  112
+		$this->assertEquals(3, count($optEls));
  113
+		$this->assertEquals('selected', (string)$optEls[0]['selected']);
  114
+		$this->assertEquals('', (string)$optEls[1]['selected']);
  115
+		$this->assertEquals('', (string)$optEls[2]['selected']);
  116
+	}
  117
+	
  118
+	function testFieldRenderingMultipleOn() {
  119
+		$choices = array('a' => 'a value', 'b' => 'b value','c' => 'c value');
  120
+		$field = new ListboxField('Choices', 'Choices', $choices);
  121
+		$field->multiple = true;
  122
+		$field->setValue('a,c');
  123
+		$parser = new CSSContentParser($field->Field());
  124
+		$optEls = $parser->getBySelector('option');
  125
+		$this->assertEquals(3, count($optEls));
  126
+		$this->assertEquals('selected', (string)$optEls[0]['selected']);
  127
+		$this->assertEquals('', (string)$optEls[1]['selected']);
  128
+		$this->assertEquals('selected', (string)$optEls[2]['selected']);
  129
+	}
  130
+	
  131
+	/**
  132
+	 * @expectedException InvalidArgumentException
  133
+	 */
  134
+	function testCommasInSourceKeys() {
  135
+		$choices = array('a' => 'a value', 'b,with,comma' => 'b value,with,comma',);
  136
+		$field = new ListboxField('Choices', 'Choices', $choices);
  137
+	}
  138
+	
  139
+}
  140
+
  141
+class ListboxFieldTest_DataObject extends DataObject implements TestOnly {
  142
+	static $db = array(
  143
+		'Choices' => 'Text'
  144
+	);
  145
+}

0 notes on commit 4d31ac6

Please sign in to comment.
Something went wrong with that request. Please try again.