diff --git a/core/model/DataObject.php b/core/model/DataObject.php index 4c8d0f840..c8723ba62 100644 --- a/core/model/DataObject.php +++ b/core/model/DataObject.php @@ -32,6 +32,12 @@ class DataObject extends ViewableData implements DataObjectInterface { */ protected $components; + /** + * DEPRECATED + * + * @var array List of fields and their old values before the last write. + */ + protected $lastWriteFields; /** * True if this DataObject has been destroyed. @@ -58,7 +64,6 @@ class DataObject extends ViewableData implements DataObjectInterface { */ static $api_access = false; - /** * Construct a new DataObject. * diff --git a/forms/CheckboxFieldDisabled.php b/forms/CheckboxFieldDisabled.php index d7c514a7a..2ca42a899 100755 --- a/forms/CheckboxFieldDisabled.php +++ b/forms/CheckboxFieldDisabled.php @@ -5,6 +5,9 @@ * @subpackage fields-basic */ class CheckboxFieldDisabled extends CheckboxField { + + protected $disabled = true; + /** * Returns a single checkbox field - used by templates. */ diff --git a/forms/CheckboxSetField.php b/forms/CheckboxSetField.php index b92815c04..219ccc2d5 100755 --- a/forms/CheckboxSetField.php +++ b/forms/CheckboxSetField.php @@ -148,6 +148,11 @@ class CheckboxSetField extends OptionsetField { } } + function performDisabledTransformation() { + $this->setDisabled(true); + return $this; + } + /** * Makes a pretty readonly field */ diff --git a/forms/CompositeDateField.php b/forms/CompositeDateField.php index 7561d7991..a99309803 100755 --- a/forms/CompositeDateField.php +++ b/forms/CompositeDateField.php @@ -148,10 +148,14 @@ JS; * @subpackage fields-datetime */ class CompositeDateField_Disabled extends DateField { + + protected $disabled = true; + function setValue($val) { if($val && $val != "0000-00-00") $this->value = date('d/m/Y', strtotime($val)); else $this->value = _t('Form.DATENOTSET', "(No date set)"); } + function Field() { if($this->value) { $df = new Date($this->name); @@ -163,6 +167,7 @@ class CompositeDateField_Disabled extends DateField { return "id() . "\">$val"; } + function Type() { return "date_disabled readonly"; } diff --git a/forms/CompositeField.php b/forms/CompositeField.php index b0f5e2901..b4fa18d55 100755 --- a/forms/CompositeField.php +++ b/forms/CompositeField.php @@ -100,11 +100,16 @@ class CompositeField extends FormField { * Add all of the non-composite fields contained within this field to the list. * Sequentialisation is used when connecting the form to its data source */ - public function collateDataFields(&$list) { + public function collateDataFields(&$list, $saveableOnly = false) { foreach($this->children as $field) { if(is_object($field)) { - if($field->isComposite()) $field->collateDataFields($list); - if($field->hasData()) { + if($field->isComposite()) $field->collateDataFields($list, $saveableOnly); + if($saveableOnly) { + $isIncluded = ($field->hasData() && !$field->isReadonly() && !$field->isDisabled()); + } else { + $isIncluded = ($field->hasData()); + } + if($isIncluded) { $name = $field->Name(); if($name) { $formName = (isset($this->form)) ? $this->form->FormName() : '(unknown form)'; diff --git a/forms/DateField.php b/forms/DateField.php index fb6a24382..fb2e090a0 100755 --- a/forms/DateField.php +++ b/forms/DateField.php @@ -30,6 +30,7 @@ class DateField extends TextField { function performReadonlyTransformation() { $field = new DateField_Disabled($this->name, $this->title, $this->value); $field->setForm($this->form); + $field->readonly = true; return $field; } @@ -90,6 +91,8 @@ JS; */ class DateField_Disabled extends DateField { + protected $disabled = true; + function setValue($val) { if($val && $val != "0000-00-00") $this->value = date('d/m/Y', strtotime($val)); else $this->value = '('._t('DateField.NODATESET', 'No date set').')'; diff --git a/forms/DropdownField.php b/forms/DropdownField.php index d651a79e6..1fd1c13a4 100755 --- a/forms/DropdownField.php +++ b/forms/DropdownField.php @@ -68,6 +68,7 @@ class DropdownField extends FormField { $field = new LookupField($this->name, $this->title, $this->source); $field->setValue($this->value); $field->setForm($this->form); + $field->setReadonly(true); return $field; } diff --git a/forms/FieldSet.php b/forms/FieldSet.php index 3453382e0..02d3350bb 100755 --- a/forms/FieldSet.php +++ b/forms/FieldSet.php @@ -15,6 +15,7 @@ class FieldSet extends DataObjectSet { * @var array */ protected $sequentialSet; + protected $sequentialSaveableSet; /** * Return a sequential set of all fields that have data. This excludes wrapper composite fields @@ -24,12 +25,22 @@ class FieldSet extends DataObjectSet { if(!$this->sequentialSet) $this->collateDataFields($this->sequentialSet); return $this->sequentialSet; } - - protected function collateDataFields(&$list) { + + public function saveableFields() { + if(!$this->sequentialSaveableSet) $this->collateDataFields($this->sequentialSaveableSet, true); + return $this->sequentialSaveableSet; + } + + protected function collateDataFields(&$list, $saveableOnly = false) { foreach($this as $field) { + if($field->isComposite()) $field->collateDataFields($list, $saveableOnly); - if($field->isComposite()) $field->collateDataFields($list); - if($field->hasData()) { + if($saveableOnly) { + $isIncluded = ($field->hasData() && !$field->isReadonly() && !$field->isDisabled()); + } else { + $isIncluded = ($field->hasData()); + } + if($isIncluded) { $name = $field->Name(); if(isset($list[$name])) { $errSuffix = ""; diff --git a/forms/Form.php b/forms/Form.php index 3e11d31a4..7a4504790 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -739,7 +739,7 @@ class Form extends RequestHandlingData { * It will make use of setCastedField() to do this. */ function saveInto(DataObjectInterface $dataObject) { - $dataFields = $this->fields->dataFields(); + $dataFields = $this->fields->saveableFields(); $lastField = null; if($dataFields) foreach($dataFields as $field) { diff --git a/forms/FormAction.php b/forms/FormAction.php index 1d2ae27b2..adf501c13 100755 --- a/forms/FormAction.php +++ b/forms/FormAction.php @@ -69,6 +69,7 @@ class FormAction extends FormField { * Globally disabled buttons would break the CMS. */ function performReadonlyTransformation() { + $this->setDisabled(true); return $this; } diff --git a/forms/FormField.php b/forms/FormField.php index 3fd3b1f4c..c74378dc2 100644 --- a/forms/FormField.php +++ b/forms/FormField.php @@ -42,6 +42,16 @@ class FormField extends RequestHandlingData { */ protected $tabIndex; + /** + * @var $readonly boolean + */ + protected $readonly = false; + + /** + * @var $disabled boolean + */ + protected $disabled = false; + /** * Create a new field. * @param name The internal field name, passed to forms. @@ -352,8 +362,36 @@ HTML; */ function hasData() { return true; } + /** + * @return boolean + */ function isReadonly() { - return !in_array($this->class, array("ReadonlyField","FormField","LookupField")); + return $this->readonly; + } + + /** + * Sets readonly-flag on form-field. Please use performReadonlyTransformation() + * to actually transform this instance. + * @param $bool boolean Setting "false" has no effect on the field-state. + */ + function setReadonly($bool) { + $this->readonly = $bool; + } + + /** + * @return boolean + */ + function isDisabled() { + return $this->disabled; + } + + /** + * Sets disabed-flag on form-field. Please use performDisabledTransformation() + * to actually transform this instance. + * @param $bool boolean Setting "false" has no effect on the field-state. + */ + function setDisabled($bool) { + $this->disabled = $bool; } /** diff --git a/forms/HiddenField.php b/forms/HiddenField.php index a9f3abfc6..7780c918b 100755 --- a/forms/HiddenField.php +++ b/forms/HiddenField.php @@ -16,6 +16,7 @@ class HiddenField extends FormField { return $this->Field(); } function performReadonlyTransformation() { + $this->setReadonly(true); return $this; } diff --git a/forms/InlineFormAction.php b/forms/InlineFormAction.php index 0c13d2e43..46564ef8d 100755 --- a/forms/InlineFormAction.php +++ b/forms/InlineFormAction.php @@ -53,6 +53,9 @@ class InlineFormAction extends FormField { * @subpackage actions */ class InlineFormAction_ReadOnly extends FormField { + + protected $readonly = true; + function Field() { return "name}\" value=\"{$this->title}\" id=\"{$this->id()}\" disabled=\"disabled\" class=\"action$extraClass\" />"; } diff --git a/forms/LiteralField.php b/forms/LiteralField.php index 4211fff7e..51330bb08 100755 --- a/forms/LiteralField.php +++ b/forms/LiteralField.php @@ -29,6 +29,7 @@ class LiteralField extends DatalessField { } function performReadonlyTransformation() { + $this->setReadonly(true); return $this; } } diff --git a/forms/LookupField.php b/forms/LookupField.php index e1f236061..c2bc55a91 100755 --- a/forms/LookupField.php +++ b/forms/LookupField.php @@ -7,6 +7,8 @@ */ class LookupField extends DropdownField { + protected $readonly = true; + /** * Returns a readonly span containing the correct value. */ @@ -40,9 +42,11 @@ class LookupField extends DropdownField { "\">$mappedValuename . "\" value=\"" . $valforInput . "\" />"; } + function performReadonlyTransformation() { return $this; } + function Type() { return "lookup readonly"; } diff --git a/forms/OptionsetField.php b/forms/OptionsetField.php index e8375cda3..8d53f298a 100755 --- a/forms/OptionsetField.php +++ b/forms/OptionsetField.php @@ -59,6 +59,7 @@ class OptionsetField extends DropdownField { $items = $this->source; $field = new LookupField($this->name,$this->title ? $this->title : "" ,$items,$this->value); $field->setForm($this->form); + $field->setReadonly(true); return $field; } diff --git a/forms/PasswordField.php b/forms/PasswordField.php index ec38fa5b6..9106b00d8 100755 --- a/forms/PasswordField.php +++ b/forms/PasswordField.php @@ -44,6 +44,7 @@ class PasswordField extends FormField { $field = new ReadonlyField($this->name, $this->title ? $this->title : '', $stars); $field->setForm($this->form); + $field->setReadonly(true); return $field; } } diff --git a/forms/ReadonlyField.php b/forms/ReadonlyField.php index e2c01d4a3..4f1bce7b3 100755 --- a/forms/ReadonlyField.php +++ b/forms/ReadonlyField.php @@ -6,6 +6,8 @@ */ class ReadonlyField extends FormField { + protected $readonly = true; + function performReadonlyTransformation() { return $this; } diff --git a/forms/SimpleImageField.php b/forms/SimpleImageField.php index 0f4d8beb7..aaabc10ae 100755 --- a/forms/SimpleImageField.php +++ b/forms/SimpleImageField.php @@ -53,6 +53,7 @@ class SimpleImageField extends FileField { function performReadonlyTransformation() { $field = new SimpleImageField_Disabled($this->name, $this->title, $this->value); $field->setForm($this->form); + $field->setReadonly(true); return $field; } } diff --git a/forms/TableField.php b/forms/TableField.php index f1b607d9c..b23fb6a0d 100644 --- a/forms/TableField.php +++ b/forms/TableField.php @@ -311,11 +311,13 @@ class TableField extends TableListField { function performReadonlyTransformation() { $this->permissions = array('show'); + $this->setReadonly(true); return $this; } function performDisabledTransformation() { $this->permissions = array('show'); + $this->setDisabled(true); return $this; } diff --git a/forms/TableListField.php b/forms/TableListField.php index 4d7015624..44a466ea7 100755 --- a/forms/TableListField.php +++ b/forms/TableListField.php @@ -488,8 +488,8 @@ JS function performReadonlyTransformation() { $this->setShowPagination(false); $this->setPermissions(array('show')); - $this->IsReadOnly = true; $this->addExtraClass( 'readonly' ); + $this->setReadonly(true); return $this; } @@ -654,11 +654,11 @@ JS * Template accessor for Permissions */ function Can($mode) { - if($mode == 'add' && $this->IsReadOnly) { + if($mode == 'add' && $this->isReadonly()) { return false; - } else if($mode == 'delete' && $this->IsReadOnly) { + } else if($mode == 'delete' && $this->isReadonly()) { return false; - } else if($mode == 'edit' && $this->IsReadOnly) { + } else if($mode == 'edit' && $this->isReadonly()) { return false; } else { return (in_array($mode, $this->permissions)); @@ -1207,7 +1207,7 @@ class TableListField_Item extends ViewableData { function MarkingCheckbox() { $name = $this->parent->Name() . '[]'; - if($this->parent->IsReadOnly || !$this->Can('edit')) + if($this->parent->isReadonly()) return "item->ID}\" disabled=\"disabled\" />"; else return "item->ID}\" />"; @@ -1234,7 +1234,7 @@ class TableListField_Item extends ViewableData { /** * Legacy: Please use permissions instead */ - function IsReadOnly() { + function isReadonly() { return $this->parent->Can('delete'); } diff --git a/forms/TimeField.php b/forms/TimeField.php index b2dbc8581..674c6730d 100755 --- a/forms/TimeField.php +++ b/forms/TimeField.php @@ -62,6 +62,8 @@ class TimeField extends TextField { */ class TimeField_Readonly extends TimeField { + protected $readonly = true; + function Field() { if( $this->value ) $val = $this->attrValue(); diff --git a/forms/TreeDropdownField.php b/forms/TreeDropdownField.php index c62422ef4..7889f2de8 100755 --- a/forms/TreeDropdownField.php +++ b/forms/TreeDropdownField.php @@ -132,6 +132,7 @@ HTML; $field = new LookupField($this->name, $this->title, $source); $field->setValue($this->value); $field->setForm($this->form); + $field->setReadonly(true); return $field; }