1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace SilverStripe\Forms; |
4
|
|
|
|
5
|
|
|
use ArrayAccess; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Represents the base class for a single-select field |
9
|
|
|
*/ |
10
|
|
|
abstract class SingleSelectField extends SelectField |
11
|
|
|
{ |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Show the first <option> element as empty (not having a value), |
15
|
|
|
* with an optional label defined through {@link $emptyString}. |
16
|
|
|
* By default, the <select> element will be rendered with the |
17
|
|
|
* first option from {@link $source} selected. |
18
|
|
|
* |
19
|
|
|
* @var bool |
20
|
|
|
*/ |
21
|
|
|
protected $hasEmptyDefault = false; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* The title shown for an empty default selection, |
25
|
|
|
* e.g. "Select...". |
26
|
|
|
* |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $emptyString = ''; |
30
|
|
|
|
31
|
|
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_SINGLESELECT; |
32
|
|
|
|
33
|
|
|
public function getSchemaStateDefaults() |
34
|
|
|
{ |
35
|
|
|
$data = parent::getSchemaStateDefaults(); |
36
|
|
|
|
37
|
|
|
// Add options to 'data' |
38
|
|
|
$data['data']['hasEmptyDefault'] = $this->getHasEmptyDefault(); |
39
|
|
|
$data['data']['emptyString'] = $this->getHasEmptyDefault() ? $this->getEmptyString() : null; |
40
|
|
|
|
41
|
|
|
$data['value'] = $this->getDefaultValue(); |
42
|
|
|
|
43
|
|
|
return $data; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
public function getDefaultValue() |
47
|
|
|
{ |
48
|
|
|
$value = $this->Value(); |
49
|
|
|
// assign value to field, such as first option available |
50
|
|
|
if ($value === null) { |
51
|
|
|
if ($this->getHasEmptyDefault()) { |
52
|
|
|
$value = ''; |
53
|
|
|
} else { |
54
|
|
|
$values = $this->getValidValues(); |
55
|
|
|
$value = array_shift($values); |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
return $value; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @param boolean $bool |
63
|
|
|
* @return self Self reference |
64
|
|
|
*/ |
65
|
|
|
public function setHasEmptyDefault($bool) |
66
|
|
|
{ |
67
|
|
|
$this->hasEmptyDefault = $bool; |
68
|
|
|
return $this; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @return bool |
73
|
|
|
*/ |
74
|
|
|
public function getHasEmptyDefault() |
75
|
|
|
{ |
76
|
|
|
return $this->hasEmptyDefault; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Set the default selection label, e.g. "select...". |
81
|
|
|
* Defaults to an empty string. Automatically sets |
82
|
|
|
* {@link $hasEmptyDefault} to true. |
83
|
|
|
* |
84
|
|
|
* @param string $string |
85
|
|
|
* @return $this |
86
|
|
|
*/ |
87
|
|
|
public function setEmptyString($string) |
88
|
|
|
{ |
89
|
|
|
$this->setHasEmptyDefault(true); |
90
|
|
|
$this->emptyString = $string; |
91
|
|
|
return $this; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @return string |
96
|
|
|
*/ |
97
|
|
|
public function getEmptyString() |
98
|
|
|
{ |
99
|
|
|
return $this->emptyString; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Gets the source array, including the empty string, if present |
104
|
|
|
* |
105
|
|
|
* @return array|ArrayAccess |
106
|
|
|
*/ |
107
|
|
|
public function getSourceEmpty() |
108
|
|
|
{ |
109
|
|
|
// Inject default option |
110
|
|
|
if ($this->getHasEmptyDefault()) { |
111
|
|
|
return array('' => $this->getEmptyString()) + $this->getSource(); |
112
|
|
|
} else { |
113
|
|
|
return $this->getSource(); |
114
|
|
|
} |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Validate this field |
119
|
|
|
* |
120
|
|
|
* @param Validator $validator |
121
|
|
|
* @return bool |
122
|
|
|
*/ |
123
|
|
|
public function validate($validator) |
124
|
|
|
{ |
125
|
|
|
// Check if valid value is given |
126
|
|
|
$selected = $this->Value(); |
127
|
|
|
$validValues = $this->getValidValues(); |
128
|
|
|
|
129
|
|
|
if (strlen($selected)) { |
130
|
|
|
// Use selection rules to check which are valid |
131
|
|
|
foreach ($validValues as $formValue) { |
132
|
|
|
if ($this->isSelectedValue($formValue, $selected)) { |
133
|
|
|
return true; |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
} else { |
137
|
|
|
if ($this->getHasEmptyDefault() || !$validValues || in_array('', $validValues)) { |
|
|
|
|
138
|
|
|
// Check empty value |
139
|
|
|
return true; |
140
|
|
|
} |
141
|
|
|
$selected = '(none)'; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
// Fail |
145
|
|
|
$validator->validationError( |
146
|
|
|
$this->name, |
147
|
|
|
_t( |
148
|
|
|
'SilverStripe\\Forms\\DropdownField.SOURCE_VALIDATION', |
149
|
|
|
"Please select a value within the list provided. {value} is not a valid option", |
150
|
|
|
array('value' => $selected) |
151
|
|
|
), |
152
|
|
|
"validation" |
153
|
|
|
); |
154
|
|
|
return false; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
public function castedCopy($classOrCopy) |
158
|
|
|
{ |
159
|
|
|
$field = parent::castedCopy($classOrCopy); |
160
|
|
|
if ($field instanceof SingleSelectField && $this->getHasEmptyDefault()) { |
161
|
|
|
$field->setEmptyString($this->getEmptyString()); |
162
|
|
|
} |
163
|
|
|
return $field; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @return SingleLookupField |
168
|
|
|
*/ |
169
|
|
|
public function performReadonlyTransformation() |
170
|
|
|
{ |
171
|
|
|
/** @var SingleLookupField $field */ |
172
|
|
|
$field = $this->castedCopy(SingleLookupField::class); |
173
|
|
|
$field->setSource($this->getSource()); |
174
|
|
|
$field->setReadonly(true); |
175
|
|
|
|
176
|
|
|
return $field; |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.