Completed
Push — master ( e1d24a...064f27 )
by Marcus
02:03
created

code/fields/MultiValueCheckboxField.php (11 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * A checkboxset that uses a multivalue field for key / val pairs
5
 *
6
 * @author [email protected]
7
 * @license BSD License http://silverstripe.org/bsd-license/
8
 */
9
class MultiValueCheckboxField extends CheckboxSetField {
10
	protected $disabled = false;
11
12
	/**
13
	 * @var Array
14
	 */
15
	protected $defaultItems = array();
16
17
	/**
18
	 * Do we store keys + values or just the values?
19
	 *
20
	 * @var boolean
21
	 */
22
	protected $storeKeys = false;
23
24
	/**
25
	 * @todo Explain different source data that can be used with this field,
26
	 * e.g. SQLMap, DataObjectSet or an array.
27
	 *
28
	 * @todo Should use CheckboxField FieldHolder rather than constructing own markup.
29
	 */
30
	function Field($properties = array()) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
31
		Requirements::css(SAPPHIRE_DIR . '/css/CheckboxSetField.css');
32
33
		$source = $this->source;
34
		$values = $this->value;
35
		if ($values instanceof MultiValueField) {
36
			$values = $values->getValues();
37
38
			if ($this->storeKeys && is_array($values)) {
39
				// use the keys instead, as that's how we've stored things
40
				$values = array_keys($values);
41
			}
42
		}
43
44
		// Get values from the join, if available
45
		if(is_object($this->form)) {
46
			$record = $this->form->getRecord();
47
			if(!$values && $record && $record->{$this->name}) {
48
				$prop = $record->{$this->name};
49
				if ($prop &&  $prop instanceof MultiValueField) {
50
					$values = $prop->getValues();
51
				}
52
			}
53
		}
54
55
		// Source is not an array
56
		if(!is_array($source) && !is_a($source, 'SQLMap')) {
57
			if(is_array($values)) {
58
				$items = $values;
59
			} else {
60
				// Source and values are DataObject sets.
61
				if($values && is_a($values, 'DataObjectSet')) {
62
					foreach($values as $object) {
63
						if(is_a($object, 'DataObject')) {
64
							$items[] = $object->ID;
65
						}
66
				   }
67
				} elseif($values && is_string($values)) {
68
					$items = explode(',', $values);
69
					$items = str_replace('{comma}', ',', $items);
70
				}
71
			}
72
		} else {
73
			// Sometimes we pass a singluar default value thats ! an array && !DataObjectSet
74
			if(is_a($values, 'DataObjectSet') || is_array($values)) {
75
				$items = $values;
76
			} else {
77
				$items = explode(',', $values);
78
				$items = str_replace('{comma}', ',', $items);
79
			}
80
		}
81
82
		if(is_array($source)) {
83
			unset($source['']);
84
		}
85
86
		$odd = 0;
87
		$options = '';
88
89
		if ($source == null) {
90
			$source = array();
91
			$options = "<li>"
92
				. _t('MultiValueCheckboxField.NoOptions', 'No options available')
93
				. "</li>";
94
		}
95
96
		if($source) foreach($source as $index => $item) {
97
			if(is_a($item, 'DataObject')) {
98
				$key = $item->ID;
99
				$value = $item->Title;
100
			} else {
101
				$key = $index;
102
				$value = $item;
103
			}
104
105
			$odd = ($odd + 1) % 2;
106
			$extraClass = $odd ? 'odd' : 'even';
107
			$extraClass .= ' val' . str_replace(' ', '', $key);
108
			$itemID = $this->id() . '_' . preg_replace('/[^a-zA-Z0-9]+/', '', $key);
109
			$checked = '';
110
111
			if(isset($items)) {
112
				$checked = (in_array($key, $items) || in_array($key, $this->defaultItems)) ? ' checked="checked"' : '';
113
			}
114
115
			$disabled = ($this->disabled || in_array($key, $this->disabledItems)) ? $disabled = ' disabled="disabled"' : '';
116
			$options .= "<li class=\"$extraClass\"><input id=\"$itemID\" name=\"$this->name[$key]\" type=\"checkbox\" value=\"$key\"$checked $disabled class=\"checkbox\" /> <label for=\"$itemID\">$value</label></li>\n";
117
		}
118
119
		return "<ul id=\"{$this->id()}\" class=\"optionset checkboxsetfield{$this->extraClass()}\">\n$options</ul>\n";
120
	}
121
122
	function setDisabled($val) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
123
		$this->disabled = $val;
124
	}
125
126
	/**
127
	 * Default selections, regardless of the {@link setValue()} settings.
128
	 * Note: Items marked as disabled through {@link setDisabledItems()} can still be
129
	 * selected by default through this method.
130
	 *
131
	 * @param Array $items Collection of array keys, as defined in the $source array
132
	 */
133
	function setDefaultItems($items) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
134
		$this->defaultItems = $items;
135
	}
136
137
	/**
138
	 * Do we store keys and values?
139
	 *
140
	 * @param boolean $val
141
	 */
142
	public function setStoreKeys($val) {
143
		$this->storeKeys = $val;
144
		return $this;
145
	}
146
147
	/**
148
	 * @return Array
149
	 */
150
	function getDefaultItems() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
151
		return $this->defaultItems;
152
	}
153
154
	/**
155
	 * Load a value into this CheckboxSetField
156
	 */
157
	function setValue($value, $obj = null) {
1 ignored issue
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Unused Code Comprehensibility introduced by
Overwriting this method does not seem to be necessary. You may want to remove this method.
Loading history...
158
		// If we're not passed a value directly, we can look for it in a relation method on the object passed as a second arg
159
//		if(!$value && $obj && $obj instanceof DataObject && $obj->hasMethod($this->name)) {
160
//			$funcName = $this->name;
161
//			$selected = $obj->$funcName();
162
//			$value = $selected->toDropdownMap('ID', 'ID');
163
//		}
164
165
		parent::setValue($value, $obj);
166
	}
167
168
	/**
169
	 * Save the current value of this CheckboxSetField into a DataObject.
170
	 * If the field it is saving to is a has_many or many_many relationship,
171
	 * it is saved by setByIDList(), otherwise it creates a comma separated
172
	 * list for a standard DB text/varchar field.
173
	 *
174
	 * @param DataObject $record The record to save into
175
	 */
176
	function saveInto(DataObjectInterface $record) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
177
178
		$fieldname = $this->name ;
179
		if($fieldname && $record) {
180
			if($this->value) {
181
				if ($this->storeKeys) {
182
					$vals = $this->getSource();
183
					if (!is_array($this->value)) {
184
						$this->value = array($this->value);
185
					}
186
					foreach ($this->value as $selected) {
187
						if (isset($vals[$selected])) {
188
							$this->value[$selected] = $vals[$selected];
189
						}
190
					}
191
				}
192
193
				$record->$fieldname = $this->value;
194
195
//				$this->value = str_replace(',', '{comma}', $this->value);
196
//				$record->$fieldname = $this->value;
197
			} else {
198
				$record->$fieldname = array();
199
			}
200
		}
201
	}
202
203
	/**
204
	 * Return the CheckboxSetField value as a string
205
	 * selected item keys.
206
	 *
207
	 * @return string
208
	 */
209
	function dataValue() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
210
		if($this->value && is_array($this->value)) {
211
			$filtered = array();
212
			foreach($this->value as $item) {
213
				if($item) {
214
					$filtered[] = str_replace(",", "{comma}", $item);
215
				}
216
			}
217
218
			return implode(',', $filtered);
219
		}
220
221
		return '';
222
	}
223
224
	function performDisabledTransformation() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
225
		$clone = clone $this;
226
		$clone->setDisabled(true);
227
228
		return $clone;
229
	}
230
231
	/**
232
	 * Transforms the source data for this CheckboxSetField
233
	 * into a comma separated list of values.
234
	 *
235
	 * @return ReadonlyField
236
	 */
237
	function performReadonlyTransformation() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
238
		$values = '';
239
		$data = array();
240
241
		$items = $this->value;
242
		if($this->source) {
243
			foreach($this->source as $source) {
244
				if(is_object($source)) {
245
					$sourceTitles[$source->ID] = $source->Title;
246
				}
247
			}
248
		}
249
250
		if($items) {
251
			// Items is a DO Set
252
			if(is_a($items, 'DataObjectSet')) {
253
				foreach($items as $item) {
254
					$data[] = $item->Title;
255
				}
256
				if($data) $values = implode(', ', $data);
257
258
			// Items is an array or single piece of string (including comma seperated string)
259
			} else {
260
				if(!is_array($items)) {
261
					$items = preg_split('/ *, */', trim($items));
262
				}
263
264
				foreach($items as $item) {
265
					if(is_array($item)) {
266
						$data[] = $item['Title'];
267
					} elseif(is_array($this->source) && !empty($this->source[$item])) {
268
						$data[] = $this->source[$item];
269
					} elseif(is_a($this->source, 'DataObjectSet')) {
270
						$data[] = $sourceTitles[$item];
271
					} else {
272
						$data[] = $item;
273
					}
274
				}
275
276
				$values = implode(', ', $data);
277
			}
278
		}
279
280
		$title = ($this->title) ? $this->title : '';
281
282
		$field = new ReadonlyField($this->name, $title, $values);
283
		$field->setForm($this->form);
284
285
		return $field;
286
	}
287
288
	function ExtraOptions() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
289
		return FormField::ExtraOptions();
290
	}
291
}
292