Merge pull request #8499 from sminnee/fix-1489

FIX: CheckboxSetField can now save into DBMultiEnum
This commit is contained in:
Loz Calver 2018-11-09 10:40:55 +01:00 committed by GitHub
commit bbb208e1dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 171 additions and 3 deletions

View File

@ -4,6 +4,7 @@ namespace SilverStripe\Forms;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\FieldType\DBMultiEnum;
use SilverStripe\ORM\Relation;
/**
@ -98,7 +99,15 @@ abstract class MultiSelectField extends SelectField
$value = array_values($relation->getIDList());
parent::setValue($value);
} elseif ($record->hasField($fieldName)) {
$value = $this->stringDecode($record->$fieldName);
// Load dataValue from field... a CSV for DBMultiEnum
if ($record->obj($fieldName) instanceof DBMultiEnum) {
$value = $this->csvDecode($record->$fieldName);
// ... JSON-encoded string for other fields
} else {
$value = $this->stringDecode($record->$fieldName);
}
parent::setValue($value);
}
}
@ -129,8 +138,14 @@ abstract class MultiSelectField extends SelectField
// Save ids into relation
$relation->setByIDList($items);
} elseif ($record->hasField($fieldName)) {
// Save dataValue into field
$record->$fieldName = $this->stringEncode($items);
// Save dataValue into field... a CSV for DBMultiEnum
if ($record->obj($fieldName) instanceof DBMultiEnum) {
$record->$fieldName = $this->csvEncode($items);
// ... JSON-encoded string for other fields
} else {
$record->$fieldName = $this->stringEncode($items);
}
}
}
@ -169,6 +184,45 @@ abstract class MultiSelectField extends SelectField
throw new \InvalidArgumentException("Invalid string encoded value for multi select field");
}
/**
* Encode a list of values into a string as a comma separated list.
* Commas will be stripped from the items passed in
*
* @param array $value
* @return string|null
*/
protected function csvEncode($value)
{
if (!$value) {
return null;
}
return implode(
',',
array_map(
function ($x) {
return str_replace(',', '', $x);
},
array_values($value)
)
);
}
/**
* Decode a list of values from a comma separated string.
* Spaces are trimmed
*
* @param string $value
* @return array
*/
protected function csvDecode($value)
{
if (!$value) {
return [];
}
return preg_split('/\s*,\s*/', trim($value));
}
/**
* Validate this field
*

View File

@ -0,0 +1,16 @@
<?php
namespace SilverStripe\Forms\Tests\CheckboxSetFieldTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
class MultiEnumArticle extends DataObject implements TestOnly
{
private static $table_name = 'CheckboxSetFieldTest_MultiEnumArticle';
private static $db = array(
"Content" => "Text",
"Colours" => "MultiEnum('Red,Blue,Green')",
);
}

View File

@ -0,0 +1,98 @@
<?php
namespace SilverStripe\Forms\Tests;
use SilverStripe\Forms\Tests\CheckboxSetFieldTest\MultiEnumArticle;
use SilverStripe\ORM\DB;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Control\Controller;
use SilverStripe\Forms\CheckboxSetField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\ORM\Connect\MySQLDatabase;
class CheckboxSetFieldMulitEnumTest extends SapphireTest
{
protected $usesDatabase = true;
public static function getExtraDataObjects()
{
// Don't add this for other database
if (DB::get_conn() instanceof MySQLDatabase) {
return [
MultiEnumArticle::class,
];
}
}
public function setUp()
{
if (!(DB::get_conn() instanceof MySQLDatabase)) {
$this->markTestSkipped('DBMultiEnum only supported by MySQL');
return;
}
parent::setUp();
}
public function tearDown()
{
if (!(DB::get_conn() instanceof MySQLDatabase)) {
return;
}
parent::tearDown();
}
public function testLoadDataFromMultiEnum()
{
$article = new MultiEnumArticle();
$article->Colours = 'Red,Green';
$field = new CheckboxSetField(
'Colours',
'Colours',
[
'Red' => 'Red',
'Blue' => 'Blue',
'Green' => 'Green',
]
);
$form = new Form(
Controller::curr(),
'Form',
new FieldList($field),
new FieldList()
);
$form->loadDataFrom($article);
$value = $field->Value();
$this->assertEquals(['Red', 'Green'], $value);
}
public function testSavingIntoMultiEnum()
{
$field = new CheckboxSetField(
'Colours',
'Colours',
[
'Red' => 'Red',
'Blue' => 'Blue',
'Green' => 'Green',
]
);
$article = new MultiEnumArticle();
$field->setValue(array('Red' => 'Red', 'Blue' => 'Blue'));
$field->saveInto($article);
$article->write();
$dbValue = DB::query(
sprintf(
'SELECT "Colours" FROM "CheckboxSetFieldTest_MultiEnumArticle" WHERE "ID" = %s',
$article->ID
)
)->value();
// JSON encoded values
$this->assertEquals('Red,Blue', $dbValue);
}
}