From 5d88950735dc4fa16cc69ad745d60abba0de9ad1 Mon Sep 17 00:00:00 2001 From: David Craig Date: Tue, 8 Mar 2016 11:54:16 +1300 Subject: [PATCH 1/6] Adds schemaDataType to FormFieldSchema --- forms/FormFieldSchemaTrait.php | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/forms/FormFieldSchemaTrait.php b/forms/FormFieldSchemaTrait.php index f4b3e09d9..35a7464e6 100644 --- a/forms/FormFieldSchemaTrait.php +++ b/forms/FormFieldSchemaTrait.php @@ -2,6 +2,8 @@ namespace SilverStripe\Forms\Schema; +use Exception; + /** * Class FormFieldSchemaTrait * @package SilverStripe\Forms\Schema @@ -15,6 +17,34 @@ namespace SilverStripe\Forms\Schema; */ trait FormFieldSchemaTrait { + /** + * The data type backing the field. Represents the type of value the + * form expects to receive via a postback. + * + * The values allowed in this list include: + * + * - String: Single line text + * - Hidden: Hidden field which is posted back without modification + * - Text: Multi line text + * - HTML: Rich html text + * - Integer: Whole number value + * - Decimal: Decimal value + * - MultiSelect: Select many from source + * - SingleSelect: Select one from source + * - Date: Date only + * - DateTime: Date and time + * - Time: Time only + * - Boolean: Yes or no + * - Custom: Custom type declared by the front-end component. For fields with this type, + * the component property is mandatory, and will determine the posted value for this field. + * - Structural: Represents a field that is NOT posted back. This may contain other fields, + * or simply be a block of stand-alone content. As with 'Custom', + * the component property is mandatory if this is assigned. + * + * @var string + */ + protected $schemaDataType; + /** * The type of front-end component to render the FormField as. * @@ -85,6 +115,14 @@ trait FormFieldSchemaTrait { return array_merge($this->getSchemaDataDefaults(), $this->schemaData); } + public function getSchemaDataType() { + if ($this->schemaDataType == null) { + throw new Exception('You need to set a schemaDataType on ' . $this->getName() . ' field'); + } + + return $this->schemaDataType; + } + /** * Gets the defaults for $schemaData. * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaData()} are ignored. @@ -94,7 +132,7 @@ trait FormFieldSchemaTrait { */ public function getSchemaDataDefaults() { return [ - 'type' => $this->class, + 'type' => $this->getSchemaDataType(), 'component' => $this->getSchemaComponent(), 'id' => $this->ID, 'holder_id' => null, From 8ae289489001448f8866a2e5dd10959b7617f45d Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 21 Mar 2016 22:54:08 +1300 Subject: [PATCH 2/6] Fix form schema ID getter Also moved keys of higher importance to start of array, easier to review this way --- forms/FormFieldSchemaTrait.php | 4 ++-- tests/forms/FormSchemaTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/forms/FormFieldSchemaTrait.php b/forms/FormFieldSchemaTrait.php index 35a7464e6..b267b4af4 100644 --- a/forms/FormFieldSchemaTrait.php +++ b/forms/FormFieldSchemaTrait.php @@ -132,11 +132,11 @@ trait FormFieldSchemaTrait { */ public function getSchemaDataDefaults() { return [ + 'name' => $this->getName(), + 'id' => $this->ID(), 'type' => $this->getSchemaDataType(), 'component' => $this->getSchemaComponent(), - 'id' => $this->ID, 'holder_id' => null, - 'name' => $this->getName(), 'title' => $this->Title(), 'source' => null, 'extraClass' => $this->ExtraClass(), diff --git a/tests/forms/FormSchemaTest.php b/tests/forms/FormSchemaTest.php index 4cf1d5564..8b586efe6 100644 --- a/tests/forms/FormSchemaTest.php +++ b/tests/forms/FormSchemaTest.php @@ -24,11 +24,11 @@ class FormSchemaTest extends SapphireTest { 'data' => [], 'fields' => [ [ - 'type' => "HiddenField", - 'component' => null, - 'id' => null, - 'holder_id' => null, + 'id' => 'Form_TestForm_SecurityID', 'name' => 'SecurityID', + 'type' => "Hidden", + 'component' => null, + 'holder_id' => null, 'title' => 'Security ID', 'source' => null, 'extraClass' => 'hidden', From adbcddee8019d5c799eeeef6ee524f95bbe8f540 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 21 Mar 2016 23:12:07 +1300 Subject: [PATCH 3/6] Only iterate through dataFields() in FormSchema Temporary measure until we implement nested fields --- forms/FormSchema.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/forms/FormSchema.php b/forms/FormSchema.php index 9f2c00dcf..06c91f207 100644 --- a/forms/FormSchema.php +++ b/forms/FormSchema.php @@ -41,10 +41,9 @@ class FormSchema { $schema['actions'][] = $action->getSchemaData(); } - foreach ($form->Fields() as $fieldList) { - foreach ($fieldList->getForm()->fields()->dataFields() as $field) { - $schema['fields'][] = $field->getSchemaData(); - } + // TODO Implemented nested fields and use Fields() instead + foreach ($form->Fields()->dataFields() as $field) { + $schema['fields'][] = $field->getSchemaData(); } return $schema; From c3a8159e80b43c9cdab61f936d2f8e626b9d2dfc Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 23 Mar 2016 14:32:14 +1300 Subject: [PATCH 4/6] Default to schema response part in LeftAndMain->schema() More of a standard API approach to return data by default, and make customisation via HTTP headers an optional mode. --- admin/code/LeftAndMain.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index 436324193..12c184030 100644 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -231,13 +231,8 @@ class LeftAndMain extends Controller implements PermissionProvider { $validHeaderValues = ['schema', 'state']; return in_array(trim($value), $validHeaderValues); }); - } - - if (!count($schemaParts)) { - throw new SS_HTTPResponse_Exception( - 'Invalid request. Check you\'ve set a "X-Formschema-Request" header with "schema" or "state" values.', - 400 - ); + } else { + $schemaParts = ['schema']; } $return = ['id' => $form->getName()]; From 3862a7a0a79428fdb18d4e4a5ae8c90381220596 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 28 Mar 2016 21:52:51 +1300 Subject: [PATCH 5/6] Moved FormFieldSchemaTrait into FormField The RFC requires a FormField implementation to override $schemaDataType, but its defined on the trait - which can't be redefined by a field subclass. In the end, the trait was never designed to be reuseable on classes other than FormField. We need to admit that architecturally, we'll have to add all that API weight to the base FormField class because of the way forms are structured in SilverStripe (mainly due to a missing layer of indirection in getCMSFields implementations). Also implemented the $schemaDataType on fields where its known. See https://github.com/silverstripe/silverstripe-framework/issues/4938 See http://php.net/manual/en/language.oop5.traits.php#language.oop5.traits.properties.example --- forms/FormField.php | 200 ++++++++++++++++++++++++++++++- forms/FormFieldSchemaTrait.php | 212 --------------------------------- 2 files changed, 198 insertions(+), 214 deletions(-) delete mode 100644 forms/FormFieldSchemaTrait.php diff --git a/forms/FormField.php b/forms/FormField.php index e324ff78a..9b0711338 100644 --- a/forms/FormField.php +++ b/forms/FormField.php @@ -20,13 +20,15 @@ * For example, data might be saved to the filesystem instead of the data record, or saved to a * component of the data record instead of the data record itself. * + * A form field can be represented as structured data through {@link FormSchema}, + * including both structure (name, id, attributes, etc.) and state (field value). + * Can be used by for JSON data which is consumed by a front-end application. + * * @package forms * @subpackage core */ class FormField extends RequestHandler { - use SilverStripe\Forms\Schema\FormFieldSchemaTrait; - /** * @var Form */ @@ -166,6 +168,57 @@ class FormField extends RequestHandler { */ protected $attributes = []; + /** + * The data type backing the field. Represents the type of value the + * form expects to receive via a postback. + * + * The values allowed in this list include: + * + * - String: Single line text + * - Hidden: Hidden field which is posted back without modification + * - Text: Multi line text + * - HTML: Rich html text + * - Integer: Whole number value + * - Decimal: Decimal value + * - MultiSelect: Select many from source + * - SingleSelect: Select one from source + * - Date: Date only + * - DateTime: Date and time + * - Time: Time only + * - Boolean: Yes or no + * - Custom: Custom type declared by the front-end component. For fields with this type, + * the component property is mandatory, and will determine the posted value for this field. + * - Structural: Represents a field that is NOT posted back. This may contain other fields, + * or simply be a block of stand-alone content. As with 'Custom', + * the component property is mandatory if this is assigned. + * + * @var string + */ + protected $schemaDataType; + + /** + * The type of front-end component to render the FormField as. + * + * @var string + */ + protected $schemaComponent; + + /** + * Structured schema data representing the FormField. + * Used to render the FormField as a ReactJS Component on the front-end. + * + * @var array + */ + protected $schemaData = []; + + /** + * Structured schema state representing the FormField's current data and validation. + * Used to render the FormField as a ReactJS Component on the front-end. + * + * @var array + */ + protected $schemaState = []; + /** * Takes a field name and converts camelcase to spaced words. Also resolves combined field * names with dot syntax to spaced words. @@ -1290,4 +1343,147 @@ class FormField extends RequestHandler { return $this->dontEscape; } + /** + * Sets the component type the FormField will be rendered as on the front-end. + * + * @param string $componentType + * @return FormField + */ + public function setSchemaComponent($componentType) { + $this->schemaComponent = $componentType; + return $this; + } + + /** + * Gets the type of front-end component the FormField will be rendered as. + * + * @return string + */ + public function getSchemaComponent() { + return $this->schemaComponent; + } + + /** + * Sets the schema data used for rendering the field on the front-end. + * Merges the passed array with the current `$schemaData` or {@link getSchemaDataDefaults()}. + * Any passed keys that are not defined in {@link getSchemaDataDefaults()} are ignored. + * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`. + * + * @param array $schemaData - The data to be merged with $this->schemaData. + * @return FormField + * + * @todo Add deep merging of arrays like `data` and `attributes`. + */ + public function setSchemaData($schemaData = []) { + $current = $this->getSchemaData(); + + $this->schemaData = array_merge($current, array_intersect_key($schemaData, $current)); + return $this; + } + + /** + * Gets the schema data used to render the FormField on the front-end. + * + * @return array + */ + public function getSchemaData() { + return array_merge($this->getSchemaDataDefaults(), $this->schemaData); + } + + /** + * @todo Throw exception if value is missing, once a form field schema is mandatory across the CMS + * + * @return string + */ + public function getSchemaDataType() { + return $this->schemaDataType; + } + + /** + * Gets the defaults for $schemaData. + * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaData()} are ignored. + * Instead the `data` array should be used to pass around ad hoc data. + * + * @return array + */ + public function getSchemaDataDefaults() { + return [ + 'name' => $this->getName(), + 'id' => $this->ID(), + 'type' => $this->getSchemaDataType(), + 'component' => $this->getSchemaComponent(), + 'holder_id' => null, + 'title' => $this->Title(), + 'source' => null, + 'extraClass' => $this->ExtraClass(), + 'description' => $this->getDescription(), + 'rightTitle' => $this->RightTitle(), + 'leftTitle' => $this->LeftTitle(), + 'readOnly' => $this->isReadOnly(), + 'disabled' => $this->isDisabled(), + 'customValidationMessage' => $this->getCustomValidationMessage(), + 'attributes' => [], + 'data' => [], + ]; + } + + /** + * Sets the schema data used for rendering the field on the front-end. + * Merges the passed array with the current `$schemaData` or {@link getSchemaDataDefaults()}. + * Any passed keys that are not defined in {@link getSchemaDataDefaults()} are ignored. + * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`. + * + * @param array $schemaData - The data to be merged with $this->schemaData. + * @return FormField + * + * @todo Add deep merging of arrays like `data` and `attributes`. + */ + public function setSchemaState($schemaState = []) { + $current = $this->getSchemaState(); + + $this->schemaState = array_merge($current, array_intersect_key($schemaState, $current)); + return $this; + } + + /** + * Gets the schema state used to render the FormField on the front-end. + * + * @return array + */ + public function getSchemaState() { + return array_merge($this->getSchemaStateDefaults(), $this->schemaState); + } + + /** + * Gets the defaults for $schemaState. + * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaState()} are ignored. + * Instead the `data` array should be used to pass around ad hoc data. + * Includes validation data if the field is associated to a {@link Form}, + * and {@link Form->validate()} has been called. + * + * @return array + */ + public function getSchemaStateDefaults() { + $field = $this; + $form = $this->getForm(); + $validator = $form ? $form->getValidator() : null; + $errors = $validator ? (array)$validator->getErrors() : []; + $messages = array_filter(array_map(function($error) use ($field) { + if($error['fieldName'] === $field->getName()) { + return [ + 'value' => $error['message'], + 'type' => $error['messageType'] + ]; + } + }, $errors)); + + return [ + 'id' => $this->ID(), + 'value' => $this->Value(), + 'valid' => (count($messages) === 0), + 'messages' => (array)$messages, + 'data' => [], + ]; + } + } diff --git a/forms/FormFieldSchemaTrait.php b/forms/FormFieldSchemaTrait.php deleted file mode 100644 index b267b4af4..000000000 --- a/forms/FormFieldSchemaTrait.php +++ /dev/null @@ -1,212 +0,0 @@ -schemaComponent = $componentType; - return $this; - } - - /** - * Gets the type of front-end component the FormField will be rendered as. - * - * @return string - */ - public function getSchemaComponent() { - return $this->schemaComponent; - } - - /** - * Sets the schema data used for rendering the field on the front-end. - * Merges the passed array with the current `$schemaData` or {@link getSchemaDataDefaults()}. - * Any passed keys that are not defined in {@link getSchemaDataDefaults()} are ignored. - * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`. - * - * @param array $schemaData - The data to be merged with $this->schemaData. - * @return FormField - * - * @todo Add deep merging of arrays like `data` and `attributes`. - */ - public function setSchemaData($schemaData = []) { - $current = $this->getSchemaData(); - - $this->schemaData = array_merge($current, array_intersect_key($schemaData, $current)); - return $this; - } - - /** - * Gets the schema data used to render the FormField on the front-end. - * - * @return array - */ - public function getSchemaData() { - return array_merge($this->getSchemaDataDefaults(), $this->schemaData); - } - - public function getSchemaDataType() { - if ($this->schemaDataType == null) { - throw new Exception('You need to set a schemaDataType on ' . $this->getName() . ' field'); - } - - return $this->schemaDataType; - } - - /** - * Gets the defaults for $schemaData. - * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaData()} are ignored. - * Instead the `data` array should be used to pass around ad hoc data. - * - * @return array - */ - public function getSchemaDataDefaults() { - return [ - 'name' => $this->getName(), - 'id' => $this->ID(), - 'type' => $this->getSchemaDataType(), - 'component' => $this->getSchemaComponent(), - 'holder_id' => null, - 'title' => $this->Title(), - 'source' => null, - 'extraClass' => $this->ExtraClass(), - 'description' => $this->getDescription(), - 'rightTitle' => $this->RightTitle(), - 'leftTitle' => $this->LeftTitle(), - 'readOnly' => $this->isReadOnly(), - 'disabled' => $this->isDisabled(), - 'customValidationMessage' => $this->getCustomValidationMessage(), - 'attributes' => [], - 'data' => [], - ]; - } - - /** - * Sets the schema data used for rendering the field on the front-end. - * Merges the passed array with the current `$schemaData` or {@link getSchemaDataDefaults()}. - * Any passed keys that are not defined in {@link getSchemaDataDefaults()} are ignored. - * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`. - * - * @param array $schemaData - The data to be merged with $this->schemaData. - * @return FormField - * - * @todo Add deep merging of arrays like `data` and `attributes`. - */ - public function setSchemaState($schemaState = []) { - $current = $this->getSchemaState(); - - $this->schemaState = array_merge($current, array_intersect_key($schemaState, $current)); - return $this; - } - - /** - * Gets the schema state used to render the FormField on the front-end. - * - * @return array - */ - public function getSchemaState() { - return array_merge($this->getSchemaStateDefaults(), $this->schemaState); - } - - /** - * Gets the defaults for $schemaState. - * The keys defined here are immutable, meaning undefined keys passed to {@link setSchemaState()} are ignored. - * Instead the `data` array should be used to pass around ad hoc data. - * Includes validation data if the field is associated to a {@link Form}, - * and {@link Form->validate()} has been called. - * - * @return array - */ - public function getSchemaStateDefaults() { - $field = $this; - $form = $this->getForm(); - $validator = $form ? $form->getValidator() : null; - $errors = $validator ? (array)$validator->getErrors() : []; - $messages = array_filter(array_map(function($error) use ($field) { - if($error['fieldName'] === $field->getName()) { - return [ - 'value' => $error['message'], - 'type' => $error['messageType'] - ]; - } - }, $errors)); - - return [ - 'id' => $this->ID(), - 'value' => $this->Value(), - 'valid' => (count($messages) === 0), - 'messages' => (array)$messages, - 'data' => [], - ]; - } -} From 55f12939bb5e172cad7b498e5ece6178e6bcecdf Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 21 Mar 2016 23:12:23 +1300 Subject: [PATCH 6/6] Defined $schemaDataType constant, added to FormField subclasses --- forms/CheckboxField.php | 2 ++ forms/CheckboxSetField.php | 2 ++ forms/CompositeField.php | 3 ++- forms/ConfirmedPasswordField.php | 2 ++ forms/CountryDropdownField.php | 2 ++ forms/CurrencyField.php | 1 - forms/DateField.php | 3 ++- forms/DatetimeField.php | 2 ++ forms/FormField.php | 46 +++++++++++++++++++++++++++++++- forms/HiddenField.php | 3 +++ forms/MoneyField.php | 2 ++ forms/MultiSelectField.php | 2 ++ forms/NumericField.php | 3 +++ forms/SingleSelectField.php | 2 ++ forms/Tab.php | 1 - forms/TextField.php | 2 ++ forms/TimeField.php | 2 ++ 17 files changed, 75 insertions(+), 5 deletions(-) diff --git a/forms/CheckboxField.php b/forms/CheckboxField.php index e88f7ca3c..b2a2895ac 100644 --- a/forms/CheckboxField.php +++ b/forms/CheckboxField.php @@ -7,6 +7,8 @@ */ class CheckboxField extends FormField { + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_SINGLESELECT; + public function setValue($value) { $this->value = ($value) ? 1 : 0; return $this; diff --git a/forms/CheckboxSetField.php b/forms/CheckboxSetField.php index 6379c749d..898ffcd9c 100644 --- a/forms/CheckboxSetField.php +++ b/forms/CheckboxSetField.php @@ -38,6 +38,8 @@ */ class CheckboxSetField extends MultiSelectField { + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_MULTISELECT; + /** * @todo Explain different source data that can be used with this field, * e.g. SQLMap, ArrayList or an array. diff --git a/forms/CompositeField.php b/forms/CompositeField.php index f137b25e1..7aa7b3ac2 100644 --- a/forms/CompositeField.php +++ b/forms/CompositeField.php @@ -43,6 +43,8 @@ class CompositeField extends FormField { */ protected $legend; + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_STRUCTURAL; + public function __construct($children = null) { if($children instanceof FieldList) { $this->children = $children; @@ -394,4 +396,3 @@ class CompositeField extends FormField { } } - diff --git a/forms/ConfirmedPasswordField.php b/forms/ConfirmedPasswordField.php index ce426708d..e5e32fc47 100644 --- a/forms/ConfirmedPasswordField.php +++ b/forms/ConfirmedPasswordField.php @@ -75,6 +75,8 @@ class ConfirmedPasswordField extends FormField { */ public $children; + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_STRUCTURAL; + /** * @param string $name * @param string $title diff --git a/forms/CountryDropdownField.php b/forms/CountryDropdownField.php index e68dd063d..b8ca28af3 100644 --- a/forms/CountryDropdownField.php +++ b/forms/CountryDropdownField.php @@ -28,6 +28,8 @@ class CountryDropdownField extends DropdownField { protected $extraClasses = array('dropdown'); + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_SINGLESELECT; + /** * Get the locale of the Member, or if we're not logged in or don't have a locale, use the default one * @return string diff --git a/forms/CurrencyField.php b/forms/CurrencyField.php index 96a8842be..baef6c8bd 100644 --- a/forms/CurrencyField.php +++ b/forms/CurrencyField.php @@ -112,4 +112,3 @@ class CurrencyField_Disabled extends CurrencyField{ . " name=\"".$this->name."\" value=\"".$valforInput."\" />"; } } - diff --git a/forms/DateField.php b/forms/DateField.php index 90065b7d7..ab6874581 100644 --- a/forms/DateField.php +++ b/forms/DateField.php @@ -60,6 +60,8 @@ require_once 'Zend/Date.php'; */ class DateField extends TextField { + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_DATE; + /** * @config * @var array @@ -677,4 +679,3 @@ class DateField_View_JQuery extends Object { return preg_replace($patterns, $replacements, $format); } } - diff --git a/forms/DatetimeField.php b/forms/DatetimeField.php index e57847ef7..e34ac4f6a 100644 --- a/forms/DatetimeField.php +++ b/forms/DatetimeField.php @@ -44,6 +44,8 @@ class DatetimeField extends FormField { */ protected $timeField = null; + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_DATETIME; + /** * @config * @var array diff --git a/forms/FormField.php b/forms/FormField.php index 9b0711338..982274537 100644 --- a/forms/FormField.php +++ b/forms/FormField.php @@ -29,6 +29,48 @@ */ class FormField extends RequestHandler { + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_STRING = 'String'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_HIDDEN = 'Hidden'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_TEXT = 'Text'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_HTML = 'HTML'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_INTEGER = 'Integer'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_DECIMAL = 'Decimal'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_MULTISELECT = 'MultiSelect'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_SINGLESELECT = 'SingleSelect'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_DATE = 'Date'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_DATETIME = 'DateTime'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_TIME = 'Time'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_BOOLEAN = 'Boolean'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_CUSTOM = 'Custom'; + + /** @see $schemaDataType */ + const SCHEMA_DATA_TYPE_STRUCTURAL = 'Structural'; + /** * @var Form */ @@ -170,7 +212,7 @@ class FormField extends RequestHandler { /** * The data type backing the field. Represents the type of value the - * form expects to receive via a postback. + * form expects to receive via a postback. Should be set in subclasses. * * The values allowed in this list include: * @@ -192,6 +234,8 @@ class FormField extends RequestHandler { * or simply be a block of stand-alone content. As with 'Custom', * the component property is mandatory if this is assigned. * + * Each value has an equivalent constant, e.g. {@link self::SCHEMA_DATA_TYPE_STRING}. + * * @var string */ protected $schemaDataType; diff --git a/forms/HiddenField.php b/forms/HiddenField.php index 052d97d5d..d03f76b18 100644 --- a/forms/HiddenField.php +++ b/forms/HiddenField.php @@ -7,6 +7,9 @@ * @subpackage fields-dataless */ class HiddenField extends FormField { + + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_HIDDEN; + /** * @param array $properties * diff --git a/forms/MoneyField.php b/forms/MoneyField.php index d8c4f15fa..5d5161a88 100644 --- a/forms/MoneyField.php +++ b/forms/MoneyField.php @@ -15,6 +15,8 @@ use SilverStripe\Model\FieldType\DBMoney; */ class MoneyField extends FormField { + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT; + /** * @var string $_locale */ diff --git a/forms/MultiSelectField.php b/forms/MultiSelectField.php index be1354088..15ba9f16d 100644 --- a/forms/MultiSelectField.php +++ b/forms/MultiSelectField.php @@ -15,6 +15,8 @@ abstract class MultiSelectField extends SelectField { */ protected $defaultItems = array(); + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_MULTISELECT; + /** * Extracts the value of this field, normalised as an array. * Scalar values will return a single length array, even if empty diff --git a/forms/NumericField.php b/forms/NumericField.php index 6a40c2778..39616cb4c 100644 --- a/forms/NumericField.php +++ b/forms/NumericField.php @@ -9,6 +9,9 @@ * @subpackage fields-formattedinput */ class NumericField extends TextField { + + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_DECIMAL; + /** * Override locale for this field. * diff --git a/forms/SingleSelectField.php b/forms/SingleSelectField.php index 186e006bf..567688fda 100644 --- a/forms/SingleSelectField.php +++ b/forms/SingleSelectField.php @@ -23,6 +23,8 @@ abstract class SingleSelectField extends SelectField { */ protected $emptyString = ''; + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_SINGLESELECT; + /** * @param boolean $bool * @return self Self reference diff --git a/forms/Tab.php b/forms/Tab.php index 3773528d2..14d53b5e1 100644 --- a/forms/Tab.php +++ b/forms/Tab.php @@ -82,4 +82,3 @@ class Tab extends CompositeField { ); } } - diff --git a/forms/TextField.php b/forms/TextField.php index f374500f8..e14ef47ef 100644 --- a/forms/TextField.php +++ b/forms/TextField.php @@ -12,6 +12,8 @@ class TextField extends FormField { */ protected $maxLength; + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT; + /** * Returns an input field. * diff --git a/forms/TimeField.php b/forms/TimeField.php index 0dc023274..6dc7c754e 100644 --- a/forms/TimeField.php +++ b/forms/TimeField.php @@ -50,6 +50,8 @@ class TimeField extends TextField { */ protected $valueObj = null; + protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TIME; + public function __construct($name, $title = null, $value = ""){ if(!$this->locale) { $this->locale = i18n::get_locale();