diff --git a/wire/modules/Inputfield/InputfieldSelect.module b/wire/modules/Inputfield/InputfieldSelect.module
index 8c2d6c8a..904c4bd4 100644
--- a/wire/modules/Inputfield/InputfieldSelect.module
+++ b/wire/modules/Inputfield/InputfieldSelect.module
@@ -9,6 +9,8 @@
* Subclasses that select multiple values should implement the InputfieldHasArrayValue interface.
*
* @property string|int $defaultValue
+ * @property array|string $options Get or set options, array of [value => label], or use options string.
+ * @property array $optionAttributes
*
*/
class InputfieldSelect extends Inputfield {
@@ -25,6 +27,14 @@ class InputfieldSelect extends Inputfield {
*/
protected $optionAttributes = array();
+ /**
+ * Alternate language labels for options, array of [ languageID => [ optionValue => optionLabel ] ]
+ *
+ * @var array
+ *
+ */
+ protected $optionLanguageLabels = array();
+
/**
* Return information about this module
*
@@ -38,6 +48,10 @@ class InputfieldSelect extends Inputfield {
);
}
+ /**
+ * Construct
+ *
+ */
public function __construct() {
parent::__construct();
$this->set('defaultValue', '');
@@ -84,6 +98,59 @@ class InputfieldSelect extends Inputfield {
return $this;
}
+ /**
+ * Set/replace all options
+ *
+ * @param array $options Array of options to add. It is assumed that array keys are the option value, and array
+ * values are the option labels, unless overridden by the $assoc argument.
+ * @param bool $assoc Is $options an associative array? (default=true). Specify false if $options is intended to be
+ * a regular PHP array, where the array keys/indexes should be ignored, and option value will also be the label.
+ * @return $this
+ *
+ */
+ public function setOptions(array $options, $assoc = true) {
+ $this->options = array();
+ return $this->addOptions($options, $assoc);
+ }
+
+ /**
+ * Get or set alternative language label(s)
+ *
+ * @param Language|int|string $language Language object, id or name (required).
+ * @param string|null|bool $key Option key/value to get/set label for,
+ * OR omit to return all currently set option language labels for language,
+ * OR boolean false to remove all language labels for this option value/key.
+ * OR array of [ optionValue => optionLabel ] to add multiple option values for language.
+ * @param $label|string|bool Translated label text to set,
+ * OR omit to GET language label.
+ * OR boolean false to remove.
+ * @return string|array|Inputfield Return value depends on given arguments
+ *
+ */
+ public function optionLanguageLabel($language, $key = null, $label = null) {
+ if(is_string($language) && !ctype_digit("$language")) {
+ $language = $this->wire('languages')->get($language);
+ }
+ $languageID = (int) "$language"; // converts Page or string to id
+ if(!isset($this->optionLanguageLabels[$languageID])) {
+ $this->optionLanguageLabels[$languageID] = array();
+ }
+ if($key === null) {
+ return $this->optionLanguageLabels[$languageID];
+ } else if($key === false) {
+ unset($this->optionLanguageLabels[$languageID]);
+ } else if(is_array($key)) {
+ foreach($key as $k => $v) $this->optionLanguageLabels[$languageID][$k] = $v;
+ } else if($label === null) {
+ return isset($this->optionLanguageLabels[$languageID][$key]) ? $this->optionLanguageLabels[$languageID][$key] : '';
+ } else if($label === false) {
+ unset($this->optionLanguageLabels[$languageID][$key]);
+ } else {
+ $this->optionLanguageLabels[$languageID][$key] = $label;
+ }
+ return $this;
+ }
+
/**
* Given a multi-line string, convert it to options, one per line
*
@@ -163,6 +230,26 @@ class InputfieldSelect extends Inputfield {
return $this;
}
+ /**
+ * Add/modify existing option labels from a line separated key=value string, primarily for multi-language support
+ *
+ * @param string $str String of optionValue=optionLabel with each on its own line
+ * @param int $languageID Language ID to set for, or omit for default language
+ *
+ */
+ protected function addOptionLabelsString($str, $languageID = 0) {
+ foreach(explode("\n", $str) as $line) {
+ $line = trim($line);
+ if(!strpos($line, '=')) continue; // 0 or false OK
+ list($key, $label) = explode('=', $line, 2);
+ if($languageID) {
+ $this->optionLanguageLabel($languageID, $key, $label);
+ } else {
+ $this->addOption($key, $label);
+ }
+ }
+ }
+
/**
* Remove the option with the given value
*
@@ -261,6 +348,75 @@ class InputfieldSelect extends Inputfield {
}
return $disabled;
}
+
+ /**
+ * Get an attributes array intended for an item (or for all items)
+ *
+ * @param string|int|null $key Option value, or omit to return ALL option attributes indexed by option value
+ * @return array Array of attributes
+ *
+ */
+ public function getOptionAttributes($key = null) {
+ if($key === null) return $this->optionAttributes;
+ if(!isset($this->optionAttributes[$key])) return array();
+ return $this->optionAttributes[$key];
+ }
+
+ /**
+ * Set/replace entire attributes array for an item
+ *
+ * @param string|int|array $key Option value, or specify associative array (indexed by option value) to set ALL option attributes
+ * @param array $attrs Array of attributes to set, or omit if you specified array for first argument.
+ * @return $this
+ *
+ */
+ public function setOptionAttributes($key, array $attrs = array()) {
+ if(is_array($key)) {
+ $this->optionAttributes = $key;
+ } else {
+ $this->optionAttributes[$key] = $attrs;
+ }
+ return $this;
+ }
+
+ /**
+ * Add attributes for an item (without removing existing attributes), or for multiple items
+ *
+ * @param string|int|array $key Option value, or array of option attributes indexed by option value.
+ * @param array $attrs Array of attributes to set, or omit if you specified array for first argument.
+ * @return $this
+ *
+ */
+ public function addOptionAttributes($key, array $attrs = array()) {
+ if(is_array($key)) {
+ foreach($key as $k => $v) {
+ $this->addOptionAttributes($k, $v);
+ }
+ } else {
+ $value = isset($this->optionAttributes[$key]) ? $this->optionAttributes[$key] : array();
+ $this->optionAttributes[$key] = array_merge($value, $attrs);
+ }
+ return $this;
+ }
+
+ /**
+ * Get an attributes string intended for the