ENHANCEMENT Allowing array values in ListboxField->setValue(), serialising into comma-separated list of values (AIR-35)

This commit is contained in:
Ingo Schommer 2011-08-29 14:31:03 +02:00
parent 007eb259e0
commit 4d31ac65a0
3 changed files with 204 additions and 1 deletions

View File

@ -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 File

@ -116,5 +116,63 @@ class ListboxField extends DropdownField {
$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 File

@ -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'
);
}