Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

249 lines (226 sloc) 6.717 kb
<?php
/**
* Dropdown field, created from a <select> tag.
*
* <b>Setting a $has_one relation</b>
*
* Using here an example of an art gallery, with Exhibition pages,
* each of which has a Gallery they belong to. The Gallery class is also user-defined.
* <code>
* static $has_one = array(
* 'Gallery' => 'Gallery',
* );
*
* public function getCMSFields() {
* $fields = parent::getCMSFields();
* $field = new DropdownField('GalleryID', 'Gallery', Gallery::get()->map('ID', 'Title'));
* $field->setEmptyString('(Select one)');
* $fields->addFieldToTab('Root.Content', $field, 'Content');
* </code>
*
* As you see, you need to put "GalleryID", rather than "Gallery" here.
*
* <b>Populate with Array</b>
*
* Example model defintion:
* <code>
* class MyObject extends DataObject {
* static $db = array(
* 'Country' => "Varchar(100)"
* );
* }
* </code>
*
* Example instantiation:
* <code>
* new DropdownField(
* 'Country',
* 'Country',
* array(
* 'NZ' => 'New Zealand',
* 'US' => 'United States'
* 'GEM'=> 'Germany'
* )
* );
* </code>
*
* <b>Populate with Enum-Values</b>
*
* You can automatically create a map of possible values from an {@link Enum} database column.
*
* Example model definition:
* <code>
* class MyObject extends DataObject {
* static $db = array(
* 'Country' => "Enum('New Zealand,United States,Germany','New Zealand')"
* );
* }
* </code>
*
* Field construction:
* <code>
* new DropdownField(
* 'Country',
* 'Country',
* singleton('MyObject')->dbObject('Country')->enumValues()
* );
* </code>
*
* @see CheckboxSetField for multiple selections through checkboxes instead.
* @see ListboxField for a single <select> box (with single or multiple selections).
* @see TreeDropdownField for a rich and customizeable UI that can visualize a tree of selectable elements
*
* @package forms
* @subpackage fields-basic
*/
class DropdownField extends FormField {
/**
* @var boolean $source Associative or numeric array of all dropdown items,
* with array key as the submitted field value, and the array value as a
* natural language description shown in the interface element.
*/
protected $source;
/**
* @var boolean $isSelected Determines if the field was selected
* at the time it was rendered, so if {@link $value} matches on of the array
* values specified in {@link $source}
*/
protected $isSelected;
/**
* @var boolean $hasEmptyDefault Show the first <option> element as
* empty (not having a value), with an optional label defined through
* {@link $emptyString}. By default, the <select> element will be
* rendered with the first option from {@link $source} selected.
*/
protected $hasEmptyDefault = false;
/**
* @var string $emptyString The title shown for an empty default selection,
* e.g. "Select...".
*/
protected $emptyString = '';
/**
* Creates a new dropdown field.
* @param $name The field name
* @param $title The field title
* @param $source An map of the dropdown items
* @param $value The current value
* @param $form The parent form
* @param $emptyString mixed Add an empty selection on to of the {@link $source}-Array (can also be boolean, which
* results in an empty string). Argument is deprecated in 3.1, please use
* {@link setEmptyString()} and/or {@link setHasEmptyDefault(true)} instead.
*/
public function __construct($name, $title=null, $source=array(), $value='', $form=null, $emptyString=null) {
$this->setSource($source);
if($emptyString === true) {
Deprecation::notice('3.1',
'Please use setHasEmptyDefault(true) instead of passing a boolean true $emptyString argument',
Deprecation::SCOPE_GLOBAL);
}
if(is_string($emptyString)) {
Deprecation::notice('3.1', 'Please use setEmptyString() instead of passing a string emptyString argument.',
Deprecation::SCOPE_GLOBAL);
}
if($emptyString) $this->setHasEmptyDefault(true);
if(is_string($emptyString)) $this->setEmptyString($emptyString);
parent::__construct($name, ($title===null) ? $name : $title, $value, $form);
}
public function Field($properties = array()) {
$source = $this->getSource();
$options = array();
if($source) {
// SQLMap needs this to add an empty value to the options
if(is_object($source) && $this->emptyString) {
$options[] = new ArrayData(array(
'Value' => '',
'Title' => $this->emptyString,
));
}
foreach($source as $value => $title) {
$selected = false;
if($value === '' && ($this->value === '' || $this->value === null)) {
$selected = true;
} else {
// check against value, fallback to a type check comparison when !value
$selected = ($value) ? $value == $this->value : $value === $this->value;
$this->isSelected = $selected;
}
$options[] = new ArrayData(array(
'Title' => $title,
'Value' => $value,
'Selected' => $selected,
));
}
}
$properties = array_merge($properties, array('Options' => new ArrayList($options)));
return parent::Field($properties);
}
public function getAttributes() {
return array_merge(
parent::getAttributes(),
array('type' => null, 'value' => null)
);
}
/**
* @return boolean
*/
public function isSelected() {
return $this->isSelected;
}
/**
* Gets the source array including any empty default values.
*
* @return array
*/
public function getSource() {
if(is_array($this->source) && $this->getHasEmptyDefault()) {
return array('' => $this->emptyString) + (array) $this->source;
} else {
return $this->source;
}
}
/**
* @param array $source
*/
public function setSource($source) {
$this->source = $source;
return $this;
}
/**
* @param boolean $bool
*/
public function setHasEmptyDefault($bool) {
$this->hasEmptyDefault = $bool;
return $this;
}
/**
* @return boolean
*/
public function getHasEmptyDefault() {
return $this->hasEmptyDefault;
}
/**
* Set the default selection label, e.g. "select...".
* Defaults to an empty string. Automatically sets
* {@link $hasEmptyDefault} to true.
*
* @param string $str
*/
public function setEmptyString($str) {
$this->setHasEmptyDefault(true);
$this->emptyString = $str;
return $this;
}
/**
* @return string
*/
public function getEmptyString() {
return $this->emptyString;
}
public function performReadonlyTransformation() {
$field = new LookupField($this->name, $this->title, $this->getSource());
$field->setValue($this->value);
$field->setForm($this->form);
$field->setReadonly(true);
return $field;
}
}
Jump to Line
Something went wrong with that request. Please try again.