mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API Copying instance props on FormField readonly/disabled transformations
Introduced new FormField->castedCopy() method which tries to replicate the existing form field instance as closely as possible. Primarily, the fix was targeted at consistently passing through FormField->description to all of its variations.
This commit is contained in:
parent
6f9d01f621
commit
559abecd56
@ -40,12 +40,6 @@ class CheckboxField extends FormField {
|
||||
$field->setForm($this->form);
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function performDisabledTransformation() {
|
||||
$clone = clone $this;
|
||||
$clone->setDisabled(true);
|
||||
return $clone;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -276,10 +276,8 @@ class CheckboxSetField extends OptionsetField {
|
||||
}
|
||||
}
|
||||
|
||||
$title = ($this->title) ? $this->title : '';
|
||||
|
||||
$field = new ReadonlyField($this->name, $title, $values);
|
||||
$field->setForm($this->form);
|
||||
$field = $this->castedCopy('ReadonlyField');
|
||||
$field->setValue($values);
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
@ -265,6 +265,8 @@ class CompositeField extends FormField {
|
||||
|
||||
$clone->children = $newChildren;
|
||||
$clone->readonly = true;
|
||||
$clone->addExtraClass($this->extraClass());
|
||||
$clone->setDescription($this->getDescription());
|
||||
|
||||
return $clone;
|
||||
}
|
||||
@ -285,6 +287,11 @@ class CompositeField extends FormField {
|
||||
|
||||
$clone->children = $newChildren;
|
||||
$clone->readonly = true;
|
||||
$clone->addExtraClass($this->extraClass());
|
||||
$clone->setDescription($this->getDescription());
|
||||
foreach($this->attributes as $k => $v) {
|
||||
$clone->setAttribute($k, $v);
|
||||
}
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
@ -320,10 +320,10 @@ class ConfirmedPasswordField extends FormField {
|
||||
* Makes a pretty readonly field with some stars in it
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
$stars = '*****';
|
||||
$field = $this->castedCopy('ReadonlyField')
|
||||
->setTitle($this->title ? $this->title : _t('Member.PASSWORD'))
|
||||
->setValue('*****');
|
||||
|
||||
$field = new ReadonlyField($this->name, $this->title ? $this->title : _t('Member.PASSWORD'), $stars);
|
||||
$field->setForm($this->form);
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,7 @@ class CurrencyField extends TextField {
|
||||
* Create a new class for this field
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new CurrencyField_Readonly($this->name, $this->title, $this->value);
|
||||
$field -> addExtraClass($this->extraClass());
|
||||
return $field;
|
||||
return $this->castedCopy('CurrencyField_Readonly');
|
||||
}
|
||||
|
||||
public function validate($validator) {
|
||||
|
@ -279,13 +279,25 @@ class DateField extends TextField {
|
||||
}
|
||||
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new DateField_Disabled($this->name, $this->title, $this->dataValue());
|
||||
$field->setForm($this->form);
|
||||
$field = $this->castedCopy('DateField_Disabled');
|
||||
$field->setValue($this->dataValue());
|
||||
$field->readonly = true;
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function castedCopy($class) {
|
||||
$copy = new $class($this->name);
|
||||
if($copy->hasMethod('setConfig')) {
|
||||
$config = $this->getConfig();
|
||||
foreach($config as $k => $v) {
|
||||
$copy->setConfig($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::castedCopy($copy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an array with expected keys 'day', 'month' and 'year.
|
||||
* Used because Zend_Date::isDate() doesn't provide this.
|
||||
|
@ -283,8 +283,22 @@ class DatetimeField extends FormField {
|
||||
}
|
||||
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new DatetimeField_Readonly($this->name, $this->title, $this->dataValue());
|
||||
$field->setForm($this->form);
|
||||
$field = $this->castedCopy('DatetimeField_Readonly');
|
||||
$field->setValue($this->dataValue());
|
||||
|
||||
$dateFieldConfig = $this->getDateField()->getConfig();
|
||||
if($dateFieldConfig) {
|
||||
foreach($dateFieldConfig as $k => $v) {
|
||||
$field->getDateField()->setConfig($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
$timeFieldConfig = $this->getTimeField()->getConfig();
|
||||
if($timeFieldConfig) {
|
||||
foreach($timeFieldConfig as $k => $v) {
|
||||
$field->getTimeField()->setConfig($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
@ -239,10 +239,10 @@ class DropdownField extends FormField {
|
||||
}
|
||||
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new LookupField($this->name, $this->title, $this->getSource());
|
||||
$field->setValue($this->value);
|
||||
$field->setForm($this->form);
|
||||
$field = $this->castedCopy('LookupField');
|
||||
$field->setSource($this->getSource());
|
||||
$field->setReadonly(true);
|
||||
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ class FormField extends RequestHandler {
|
||||
'id' => $this->ID(),
|
||||
'disabled' => $this->isDisabled(),
|
||||
);
|
||||
|
||||
|
||||
return array_merge($attrs, $this->attributes);
|
||||
}
|
||||
|
||||
@ -709,10 +709,9 @@ class FormField extends RequestHandler {
|
||||
* Returns a readonly version of this field
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new ReadonlyField($this->name, $this->title, $this->value);
|
||||
$field->addExtraClass($this->extraClass());
|
||||
$field->setForm($this->form);
|
||||
return $field;
|
||||
$copy = $this->castedCopy('ReadonlyField');
|
||||
$copy->setReadonly(true);
|
||||
return $copy;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -723,14 +722,15 @@ class FormField extends RequestHandler {
|
||||
* @return FormField
|
||||
*/
|
||||
public function performDisabledTransformation() {
|
||||
$clone = clone $this;
|
||||
$disabledClassName = $clone->class . '_Disabled';
|
||||
$disabledClassName = $this->class . '_Disabled';
|
||||
if(ClassInfo::exists($disabledClassName)) {
|
||||
return new $disabledClassName($this->name, $this->title, $this->value);
|
||||
$clone = $this->castedCopy($disabledClassName);
|
||||
} else {
|
||||
$clone = clone $this;
|
||||
$clone->setDisabled(true);
|
||||
return $clone;
|
||||
}
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
public function transform(FormTransformation $trans) {
|
||||
@ -774,7 +774,8 @@ class FormField extends RequestHandler {
|
||||
|
||||
/**
|
||||
* Describe this field, provide help text for it.
|
||||
* By default, renders as a "title" attribute on the form field.
|
||||
* By default, renders as a <span class="description">
|
||||
* underneath the form field.
|
||||
*
|
||||
* @return string Description
|
||||
*/
|
||||
@ -828,5 +829,43 @@ class FormField extends RequestHandler {
|
||||
if(is_object($this->containerFieldList)) return $this->containerFieldList->rootFieldList();
|
||||
else user_error("rootFieldList() called on $this->class object without a containerFieldList", E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns another instance of this field, but "cast" to a different class.
|
||||
* The logic tries to retain all of the instance properties,
|
||||
* and may be overloaded by subclasses to set additional ones.
|
||||
*
|
||||
* Assumes the standard FormField parameter signature with
|
||||
* its name as the only mandatory argument. Mainly geared towards
|
||||
* creating *_Readonly or *_Disabled subclasses of the same type,
|
||||
* or casting to a {@link ReadonlyField}.
|
||||
*
|
||||
* Does not copy custom field templates, since they probably won't apply to
|
||||
* the new instance.
|
||||
*
|
||||
* @param String $classOrCopy Class name for copy, or existing copy instance to update
|
||||
* @return FormField
|
||||
*/
|
||||
public function castedCopy($classOrCopy) {
|
||||
$field = (is_object($classOrCopy)) ? $classOrCopy : new $classOrCopy($this->name);
|
||||
$field
|
||||
->setValue($this->value) // get value directly from property, avoid any conversions
|
||||
->setForm($this->form)
|
||||
->setTitle($this->Title())
|
||||
->setLeftTitle($this->LeftTitle())
|
||||
->setRightTitle($this->RightTitle())
|
||||
->addExtraClass($this->extraClass())
|
||||
->setDescription($this->getDescription());
|
||||
|
||||
// Only include built-in attributes, ignore anything
|
||||
// set through getAttributes(), since those might change important characteristics
|
||||
// of the field, e.g. its "type" attribute.
|
||||
foreach($this->attributes as $k => $v) {
|
||||
$field->setAttribute($k, $v);
|
||||
}
|
||||
$field->dontEscape = $this->dontEscape;
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -204,9 +204,9 @@ class HtmlEditorField extends TextareaField {
|
||||
* @return HtmlEditorField_Readonly
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new HtmlEditorField_Readonly($this->name, $this->title, $this->value);
|
||||
$field->setForm($this->form);
|
||||
$field = $this->castedCopy('HtmlEditorField_Readonly');
|
||||
$field->dontEscape = true;
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class InlineFormAction extends FormField {
|
||||
}
|
||||
|
||||
public function performReadonlyTransformation() {
|
||||
return new InlineFormAction_ReadOnly( $this->name, $this->title );
|
||||
return $this->castedCopy('InlineFormAction_ReadOnly');
|
||||
}
|
||||
|
||||
public function Field($properties = array()) {
|
||||
|
@ -32,7 +32,7 @@ class LookupField extends DropdownField {
|
||||
|
||||
// Don't check if string arguments are matching against the source,
|
||||
// as they might be generated HTML diff views instead of the actual values
|
||||
if($this->value && !$mapped) {
|
||||
if($this->value && !is_array($this->value) && !$mapped) {
|
||||
$mapped = array(trim($this->value));
|
||||
$values = array();
|
||||
}
|
||||
|
@ -92,9 +92,8 @@ class OptionsetField extends DropdownField {
|
||||
|
||||
public function performReadonlyTransformation() {
|
||||
// Source and values are DataObject sets.
|
||||
$items = $this->getSource();
|
||||
$field = new LookupField($this->name, $this->title ? $this->title : '', $items, $this->value);
|
||||
$field->setForm($this->form);
|
||||
$field = $this->castedCopy('LookupField');
|
||||
$field->setValue($this->getSource());
|
||||
$field->setReadonly(true);
|
||||
|
||||
return $field;
|
||||
|
@ -31,11 +31,9 @@ class PasswordField extends TextField {
|
||||
* Makes a pretty readonly field with some stars in it
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
$stars = '*****';
|
||||
|
||||
$field = new ReadonlyField($this->name, $this->title ? $this->title : '', $stars);
|
||||
$field->setForm($this->form);
|
||||
$field->setReadonly(true);
|
||||
$field = $this->castedCopy('ReadonlyField');
|
||||
$field->setValue('*****');
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
|
@ -44,20 +44,6 @@ class TextareaField extends FormField {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a disabled transformation on this field. You shouldn't be able to
|
||||
* copy from this field, and it should not send any data when you submit the
|
||||
* form it's attached to.
|
||||
*
|
||||
* The element shouldn't be both disabled and readonly at the same time.
|
||||
*/
|
||||
public function performDisabledTransformation() {
|
||||
$clone = clone $this;
|
||||
$clone->setDisabled(true);
|
||||
$clone->setReadonly(false);
|
||||
return $clone;
|
||||
}
|
||||
|
||||
public function Type() {
|
||||
return parent::Type() . ($this->readonly ? ' readonly' : '');
|
||||
}
|
||||
|
@ -191,7 +191,19 @@ class TimeField extends TextField {
|
||||
* Creates a new readonly field specified below
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
return new TimeField_Readonly($this->name, $this->title, $this->dataValue(), $this->getConfig('timeformat'));
|
||||
return $this->castedCopy('TimeField_Readonly');
|
||||
}
|
||||
|
||||
public function castedCopy($class) {
|
||||
$copy = parent::castedCopy($class);
|
||||
if($copy->hasMethod('setConfig')) {
|
||||
$config = $this->getConfig();
|
||||
foreach($config as $k => $v) {
|
||||
$copy->setConfig($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -291,6 +291,48 @@ class TreeDropdownField extends FormField {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String $field
|
||||
*/
|
||||
public function setLabelField($field) {
|
||||
$this->labelField = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String
|
||||
*/
|
||||
public function getLabelField() {
|
||||
return $this->labelField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String $field
|
||||
*/
|
||||
public function setKeyField($field) {
|
||||
$this->keyField = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String
|
||||
*/
|
||||
public function getKeyField() {
|
||||
return $this->keyField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String $field
|
||||
*/
|
||||
public function setSourceObject($class) {
|
||||
$this->sourceObject = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String
|
||||
*/
|
||||
public function getSourceObject() {
|
||||
return $this->sourceObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate $this->searchIds with the IDs of the pages matching the searched parameter and their parents.
|
||||
@ -342,9 +384,14 @@ class TreeDropdownField extends FormField {
|
||||
* Changes this field to the readonly field.
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
return new TreeDropdownField_Readonly($this->name, $this->title, $this->sourceObject, $this->keyField,
|
||||
$this->labelField);
|
||||
$copy = $this->castedCopy('TreeDropdownField_Readonly');
|
||||
$copy->setKeyField($this->keyField);
|
||||
$copy->setLabelField($this->labelField);
|
||||
$copy->setSourceObject($this->sourceObject);
|
||||
|
||||
return $copy;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,14 +175,12 @@ class TreeMultiselectField extends TreeDropdownField {
|
||||
* Changes this field to the readonly field.
|
||||
*/
|
||||
public function performReadonlyTransformation() {
|
||||
$field = new TreeMultiselectField_Readonly($this->name, $this->title, $this->sourceObject,
|
||||
$this->keyField, $this->labelField);
|
||||
$copy = $this->castedCopy('TreeMultiselectField_Readonly');
|
||||
$copy->setKeyField($this->keyField);
|
||||
$copy->setLabelField($this->labelField);
|
||||
$copy->setSourceObject($this->sourceObject);
|
||||
|
||||
$field->addExtraClass($this->extraClass());
|
||||
$field->setForm($this->form);
|
||||
$field->setValue($this->value);
|
||||
|
||||
return $field;
|
||||
return $copy;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,7 @@ class CheckboxFieldTest extends SapphireTest {
|
||||
// Test 1: a checked checkbox goes to "Yes"
|
||||
$field1 = new CheckboxField('IsChecked', 'Checked');
|
||||
$field1->setValue('on');
|
||||
$copy = $field1->performReadonlyTransformation();
|
||||
$this->assertEquals(_t('CheckboxField.YES', 'Yes'),
|
||||
trim(strip_tags($field1->performReadonlyTransformation()->Field())));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user