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;
}