mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Initial Form Field Schema implementation
- Adds FormSchema class - Adds FormSchema dependency to LeftAndMain via Injector - Adds schema allowed_action method to LeftAndMain for generating Form schemas - Adds FormFieldSchemaTrait to for schema getters and setters on FormFields
This commit is contained in:
parent
827d989836
commit
afccef718c
@ -1,6 +1,9 @@
|
||||
---
|
||||
Name: coreconfig
|
||||
---
|
||||
Injector:
|
||||
FormSchema:
|
||||
class: SilverStripe\Forms\Schema\FormSchema
|
||||
Upload:
|
||||
# Replace an existing file rather than renaming the new one.
|
||||
replaceFile: false
|
||||
|
@ -5,6 +5,8 @@
|
||||
* @subpackage admin
|
||||
*/
|
||||
|
||||
use SilverStripe\Forms\Schema\FormSchema;
|
||||
|
||||
/**
|
||||
* LeftAndMain is the parent class of all the two-pane views in the CMS.
|
||||
* If you are wanting to add more areas to the CMS, you can do it by subclassing LeftAndMain.
|
||||
@ -84,7 +86,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_actions = array(
|
||||
private static $allowed_actions = [
|
||||
'index',
|
||||
'save',
|
||||
'savetreenode',
|
||||
@ -97,7 +99,12 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
'AddForm',
|
||||
'batchactions',
|
||||
'BatchActionsForm',
|
||||
);
|
||||
'schema',
|
||||
];
|
||||
|
||||
private static $dependencies = [
|
||||
'schema' => '%$FormSchema'
|
||||
];
|
||||
|
||||
/**
|
||||
* @config
|
||||
@ -169,6 +176,15 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
*/
|
||||
protected $responseNegotiator;
|
||||
|
||||
/**
|
||||
* Gets a JSON schema representing the current edit form.
|
||||
*
|
||||
* @return SS_HTTPResponse
|
||||
*/
|
||||
public function schema() {
|
||||
return $this->schema->getSchema($this->getEditForm());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member $member
|
||||
* @return boolean
|
||||
|
@ -25,6 +25,8 @@
|
||||
*/
|
||||
class FormField extends RequestHandler {
|
||||
|
||||
use SilverStripe\Forms\Schema\FormFieldSchemaTrait;
|
||||
|
||||
/**
|
||||
* @var Form
|
||||
*/
|
||||
@ -80,7 +82,7 @@ class FormField extends RequestHandler {
|
||||
* @config
|
||||
* @var array $default_classes The default classes to apply to the FormField
|
||||
*/
|
||||
private static $default_classes = array();
|
||||
private static $default_classes = [];
|
||||
|
||||
|
||||
/**
|
||||
@ -162,7 +164,22 @@ class FormField extends RequestHandler {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = array();
|
||||
protected $attributes = [];
|
||||
|
||||
/**
|
||||
* 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 = [];
|
||||
|
||||
/**
|
||||
* Takes a field name and converts camelcase to spaced words. Also resolves combined field
|
||||
|
81
forms/FormFieldSchemaTrait.php
Normal file
81
forms/FormFieldSchemaTrait.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Schema;
|
||||
|
||||
trait FormFieldSchemaTrait {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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' => [],
|
||||
];
|
||||
}
|
||||
}
|
56
forms/FormSchema.php
Normal file
56
forms/FormSchema.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Schema;
|
||||
|
||||
use Convert;
|
||||
use Form;
|
||||
|
||||
class FormSchema {
|
||||
|
||||
/**
|
||||
* Gets the schema for this form as a nested array.
|
||||
*
|
||||
* @param Form $form
|
||||
* @return string
|
||||
*/
|
||||
public function getSchema(Form $form) {
|
||||
$request = $form->controller()->getRequest();
|
||||
$params = $request->AllParams();
|
||||
|
||||
$schema = [
|
||||
'name' => $form->getName(),
|
||||
'id' => isset($params['ID']) ? $params['ID'] : null,
|
||||
'action' => isset($params['Action']) ? $params['Action'] : null,
|
||||
'method' => $form->controller()->getRequest()->HttpMethod(),
|
||||
'schema_url' => $request->getUrl(),
|
||||
'attributes' => $form->getAttributes(),
|
||||
'data' => [],
|
||||
'fields' => [],
|
||||
'actions' => []
|
||||
];
|
||||
|
||||
foreach ($form->Actions() as $action) {
|
||||
$schema['actions'][] = $action->getSchemaData();
|
||||
}
|
||||
|
||||
foreach ($form->Fields() as $fieldList) {
|
||||
foreach ($fieldList->getForm()->fields()->dataFields() as $field) {
|
||||
$schema['fields'][] = $field->getSchemaData();
|
||||
}
|
||||
}
|
||||
|
||||
return Convert::raw2json($schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current state of this form as a nested array.
|
||||
*
|
||||
* @param From $form
|
||||
* @return string
|
||||
*/
|
||||
public function getState(Form $form) {
|
||||
$state = ['state' => []];
|
||||
|
||||
return Convert::raw2json($state);
|
||||
}
|
||||
}
|
@ -241,6 +241,43 @@ class FormFieldTest extends SapphireTest {
|
||||
$this->assertArrayHasKey('extended', $field->getAttributes());
|
||||
}
|
||||
|
||||
public function testSetSchemaComponent() {
|
||||
$field = new FormField('MyField');
|
||||
$field = $field->setSchemaComponent('MyComponent');
|
||||
$component = $field->getSchemaComponent();
|
||||
$this->assertEquals('MyComponent', $component);
|
||||
}
|
||||
|
||||
public function testGetSchemaDataDefaults() {
|
||||
$field = new FormField('MyField');
|
||||
$schema = $field->getSchemaDataDefaults();
|
||||
$this->assertInternalType('array', $schema);
|
||||
}
|
||||
|
||||
public function testGetSchemaData() {
|
||||
$field = new FormField('MyField');
|
||||
$schema = $field->getSchemaData();
|
||||
$this->assertEquals('MyField', $schema['name']);
|
||||
|
||||
// Make sure the schema data is up-to-date with object properties.
|
||||
$field->setName('UpdatedField');
|
||||
$schema = $field->getSchemaData();
|
||||
$this->assertEquals($field->getName(), $schema['name']);
|
||||
}
|
||||
|
||||
public function testSetSchemaData() {
|
||||
$field = new FormField('MyField');
|
||||
|
||||
// Make sure the user can update values.
|
||||
$field = $field->setSchemaData(['name' => 'MyUpdatedField']);
|
||||
$schema = $field->getSchemaData();
|
||||
$this->assertEquals($schema['name'], 'MyUpdatedField');
|
||||
|
||||
// Make user the user can't define custom keys on the schema.
|
||||
$field = $field->setSchemaData(['myCustomKey' => 'yolo']);
|
||||
$schema = $field->getSchemaData();
|
||||
$this->assertEquals(array_key_exists('myCustomKey', $schema), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
62
tests/forms/FormSchemaTest.php
Normal file
62
tests/forms/FormSchemaTest.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Forms\Schema\FormSchema;
|
||||
|
||||
class FormSchemaTest extends SapphireTest {
|
||||
|
||||
public function testGetSchema() {
|
||||
$form = new Form(new Controller(), 'TestForm', new FieldList(), new FieldList());
|
||||
$formSchema = new FormSchema();
|
||||
$expectedJSON = json_encode([
|
||||
'name' => 'TestForm',
|
||||
'id' => null,
|
||||
'action' => null,
|
||||
'method' => '',
|
||||
'schema_url' => '',
|
||||
'attributes' => [
|
||||
'id' => 'Form_TestForm',
|
||||
'action' => 'Controller/TestForm',
|
||||
'method' => 'POST',
|
||||
'enctype' => 'application/x-www-form-urlencoded',
|
||||
'target' => null,
|
||||
'class' => ''
|
||||
],
|
||||
'data' => [],
|
||||
'fields' => [
|
||||
[
|
||||
'type' => "HiddenField",
|
||||
'component' => null,
|
||||
'id' => null,
|
||||
'holder_id' => null,
|
||||
'name' => 'SecurityID',
|
||||
'title' => 'Security ID',
|
||||
'source' => null,
|
||||
'extraClass' => 'hidden',
|
||||
'description' => null,
|
||||
'rightTitle' => null,
|
||||
'leftTitle' => null,
|
||||
'readOnly' => false,
|
||||
'disabled' => false,
|
||||
'customValidationMessage' => '',
|
||||
'attributes' => [],
|
||||
'data' => []
|
||||
],
|
||||
],
|
||||
'actions' => []
|
||||
]);
|
||||
|
||||
$schema = $formSchema->getSchema($form);
|
||||
|
||||
$this->assertJsonStringEqualsJsonString($expectedJSON, $schema);
|
||||
}
|
||||
|
||||
public function testGetState() {
|
||||
$form = new Form(new Controller(), 'TestForm', new FieldList(), new FieldList());
|
||||
$formSchema = new FormSchema();
|
||||
$expectedJSON = json_encode(['state' => []]);
|
||||
|
||||
$state = $formSchema->getState($form);
|
||||
|
||||
$this->assertJsonStringEqualsJsonString($expectedJSON, $state);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user