mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #5239 from open-sausages/pulls/4.0/form-schema-fixes
Form schema fixes
This commit is contained in:
commit
0fa7271ec2
@ -231,13 +231,8 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
|||||||
$validHeaderValues = ['schema', 'state'];
|
$validHeaderValues = ['schema', 'state'];
|
||||||
return in_array(trim($value), $validHeaderValues);
|
return in_array(trim($value), $validHeaderValues);
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
|
$schemaParts = ['schema'];
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$return = ['id' => $form->getName()];
|
$return = ['id' => $form->getName()];
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
class CheckboxField extends FormField {
|
class CheckboxField extends FormField {
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_SINGLESELECT;
|
||||||
|
|
||||||
public function setValue($value) {
|
public function setValue($value) {
|
||||||
$this->value = ($value) ? 1 : 0;
|
$this->value = ($value) ? 1 : 0;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
*/
|
*/
|
||||||
class CheckboxSetField extends MultiSelectField {
|
class CheckboxSetField extends MultiSelectField {
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_MULTISELECT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Explain different source data that can be used with this field,
|
* @todo Explain different source data that can be used with this field,
|
||||||
* e.g. SQLMap, ArrayList or an array.
|
* e.g. SQLMap, ArrayList or an array.
|
||||||
|
@ -43,6 +43,8 @@ class CompositeField extends FormField {
|
|||||||
*/
|
*/
|
||||||
protected $legend;
|
protected $legend;
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_STRUCTURAL;
|
||||||
|
|
||||||
public function __construct($children = null) {
|
public function __construct($children = null) {
|
||||||
if($children instanceof FieldList) {
|
if($children instanceof FieldList) {
|
||||||
$this->children = $children;
|
$this->children = $children;
|
||||||
@ -394,4 +396,3 @@ class CompositeField extends FormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ class ConfirmedPasswordField extends FormField {
|
|||||||
*/
|
*/
|
||||||
public $children;
|
public $children;
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_STRUCTURAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param string $title
|
* @param string $title
|
||||||
|
@ -28,6 +28,8 @@ class CountryDropdownField extends DropdownField {
|
|||||||
|
|
||||||
protected $extraClasses = array('dropdown');
|
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
|
* 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
|
* @return string
|
||||||
|
@ -112,4 +112,3 @@ class CurrencyField_Disabled extends CurrencyField{
|
|||||||
. " name=\"".$this->name."\" value=\"".$valforInput."\" />";
|
. " name=\"".$this->name."\" value=\"".$valforInput."\" />";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,8 @@ require_once 'Zend/Date.php';
|
|||||||
*/
|
*/
|
||||||
class DateField extends TextField {
|
class DateField extends TextField {
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_DATE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
* @var array
|
* @var array
|
||||||
@ -677,4 +679,3 @@ class DateField_View_JQuery extends Object {
|
|||||||
return preg_replace($patterns, $replacements, $format);
|
return preg_replace($patterns, $replacements, $format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@ class DatetimeField extends FormField {
|
|||||||
*/
|
*/
|
||||||
protected $timeField = null;
|
protected $timeField = null;
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_DATETIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
* @var array
|
* @var array
|
||||||
|
@ -20,12 +20,56 @@
|
|||||||
* For example, data might be saved to the filesystem instead of the data record, or saved to a
|
* 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.
|
* 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
|
* @package forms
|
||||||
* @subpackage core
|
* @subpackage core
|
||||||
*/
|
*/
|
||||||
class FormField extends RequestHandler {
|
class FormField extends RequestHandler {
|
||||||
|
|
||||||
use SilverStripe\Forms\Schema\FormFieldSchemaTrait;
|
/** @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
|
* @var Form
|
||||||
@ -166,6 +210,59 @@ class FormField extends RequestHandler {
|
|||||||
*/
|
*/
|
||||||
protected $attributes = [];
|
protected $attributes = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data type backing the field. Represents the type of value the
|
||||||
|
* form expects to receive via a postback. Should be set in subclasses.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Each value has an equivalent constant, e.g. {@link self::SCHEMA_DATA_TYPE_STRING}.
|
||||||
|
*
|
||||||
|
* @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
|
* Takes a field name and converts camelcase to spaced words. Also resolves combined field
|
||||||
* names with dot syntax to spaced words.
|
* names with dot syntax to spaced words.
|
||||||
@ -1290,4 +1387,147 @@ class FormField extends RequestHandler {
|
|||||||
return $this->dontEscape;
|
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' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\Forms\Schema;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class FormFieldSchemaTrait
|
|
||||||
* @package SilverStripe\Forms\Schema
|
|
||||||
*
|
|
||||||
* Allows {@link FormField} to be represented as structured data,
|
|
||||||
* including both structure (name, id, attributes, etc.) and state (field value).
|
|
||||||
* Can be used by {@link FormSchema} to represent a form in JSON,
|
|
||||||
* to be consumed by a front-end application.
|
|
||||||
*
|
|
||||||
* WARNING: Experimental API.
|
|
||||||
*/
|
|
||||||
trait FormFieldSchemaTrait {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 [
|
|
||||||
'type' => $this->class,
|
|
||||||
'component' => $this->getSchemaComponent(),
|
|
||||||
'id' => $this->ID,
|
|
||||||
'holder_id' => null,
|
|
||||||
'name' => $this->getName(),
|
|
||||||
'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' => [],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -41,11 +41,10 @@ class FormSchema {
|
|||||||
$schema['actions'][] = $action->getSchemaData();
|
$schema['actions'][] = $action->getSchemaData();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($form->Fields() as $fieldList) {
|
// TODO Implemented nested fields and use Fields() instead
|
||||||
foreach ($fieldList->getForm()->fields()->dataFields() as $field) {
|
foreach ($form->Fields()->dataFields() as $field) {
|
||||||
$schema['fields'][] = $field->getSchemaData();
|
$schema['fields'][] = $field->getSchemaData();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $schema;
|
return $schema;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
* @subpackage fields-dataless
|
* @subpackage fields-dataless
|
||||||
*/
|
*/
|
||||||
class HiddenField extends FormField {
|
class HiddenField extends FormField {
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_HIDDEN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $properties
|
* @param array $properties
|
||||||
*
|
*
|
||||||
|
@ -15,6 +15,8 @@ use SilverStripe\Model\FieldType\DBMoney;
|
|||||||
*/
|
*/
|
||||||
class MoneyField extends FormField {
|
class MoneyField extends FormField {
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string $_locale
|
* @var string $_locale
|
||||||
*/
|
*/
|
||||||
|
@ -15,6 +15,8 @@ abstract class MultiSelectField extends SelectField {
|
|||||||
*/
|
*/
|
||||||
protected $defaultItems = array();
|
protected $defaultItems = array();
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_MULTISELECT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the value of this field, normalised as an array.
|
* Extracts the value of this field, normalised as an array.
|
||||||
* Scalar values will return a single length array, even if empty
|
* Scalar values will return a single length array, even if empty
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
* @subpackage fields-formattedinput
|
* @subpackage fields-formattedinput
|
||||||
*/
|
*/
|
||||||
class NumericField extends TextField {
|
class NumericField extends TextField {
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_DECIMAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override locale for this field.
|
* Override locale for this field.
|
||||||
*
|
*
|
||||||
|
@ -23,6 +23,8 @@ abstract class SingleSelectField extends SelectField {
|
|||||||
*/
|
*/
|
||||||
protected $emptyString = '';
|
protected $emptyString = '';
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_SINGLESELECT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param boolean $bool
|
* @param boolean $bool
|
||||||
* @return self Self reference
|
* @return self Self reference
|
||||||
|
@ -82,4 +82,3 @@ class Tab extends CompositeField {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ class TextField extends FormField {
|
|||||||
*/
|
*/
|
||||||
protected $maxLength;
|
protected $maxLength;
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an input field.
|
* Returns an input field.
|
||||||
*
|
*
|
||||||
|
@ -50,6 +50,8 @@ class TimeField extends TextField {
|
|||||||
*/
|
*/
|
||||||
protected $valueObj = null;
|
protected $valueObj = null;
|
||||||
|
|
||||||
|
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TIME;
|
||||||
|
|
||||||
public function __construct($name, $title = null, $value = ""){
|
public function __construct($name, $title = null, $value = ""){
|
||||||
if(!$this->locale) {
|
if(!$this->locale) {
|
||||||
$this->locale = i18n::get_locale();
|
$this->locale = i18n::get_locale();
|
||||||
|
@ -24,11 +24,11 @@ class FormSchemaTest extends SapphireTest {
|
|||||||
'data' => [],
|
'data' => [],
|
||||||
'fields' => [
|
'fields' => [
|
||||||
[
|
[
|
||||||
'type' => "HiddenField",
|
'id' => 'Form_TestForm_SecurityID',
|
||||||
'component' => null,
|
|
||||||
'id' => null,
|
|
||||||
'holder_id' => null,
|
|
||||||
'name' => 'SecurityID',
|
'name' => 'SecurityID',
|
||||||
|
'type' => "Hidden",
|
||||||
|
'component' => null,
|
||||||
|
'holder_id' => null,
|
||||||
'title' => 'Security ID',
|
'title' => 'Security ID',
|
||||||
'source' => null,
|
'source' => null,
|
||||||
'extraClass' => 'hidden',
|
'extraClass' => 'hidden',
|
||||||
|
Loading…
Reference in New Issue
Block a user