Refactor form widget to use an approach much like ReportContainer

This commit is contained in:
Samuel Georges 2015-02-28 13:37:06 +11:00
parent 6e54fea23f
commit f9e287e173
2 changed files with 121 additions and 117 deletions

View File

@ -28,7 +28,7 @@ class Filter extends WidgetBase
* @var string The context of this filter, scopes that do not belong * @var string The context of this filter, scopes that do not belong
* to this context will not be shown. * to this context will not be shown.
*/ */
protected $context = null; public $context = null;
// //
// Object properties // Object properties

View File

@ -23,27 +23,24 @@ use October\Rain\Database\Model;
*/ */
class Form extends WidgetBase class Form extends WidgetBase
{ {
/** //
* @var array Expected configuration: // Configurable properties
* //
* - fields: outside form field definitions
* - tabs: primary tab form field definitions
* - secondaryTabs: secondary tab form field definitions
* - arrayName: a HTML array name to use for each element
* - context: apply a context to this form and its fields
*/
public $config = [
'fields' => [],
'tabs' => [],
'secondaryTabs' => [],
'arrayName' => null,
'context' => null,
];
/** /**
* {@inheritDoc} * @var array Form field configuration.
*/ */
protected $defaultAlias = 'form'; public $fields;
/**
* @var array Primary tab configuration.
*/
public $tabs;
/**
* @var array Secondary tab configuration.
*/
public $secondaryTabs;
/** /**
* @var Model Form model object. * @var Model Form model object.
@ -56,34 +53,10 @@ class Form extends WidgetBase
public $data; public $data;
/** /**
* @var boolean Determines if field definitions have been created. * @var string The context of this form, fields that do not belong
* to this context will not be shown.
*/ */
protected $fieldsDefined = false; public $context = null;
/**
* @var array Collection of all fields used in this form.
*/
protected $fields = [];
/**
* @var array Collection of all form widgets used in this form.
*/
protected $formWidgets = [];
/**
* @var Backend\Classes\FormTabs Collection of fields not contained in a tab.
*/
protected $outsideTabs;
/**
* @var Backend\Classes\FormTabs Collection of fields inside the primary tabs.
*/
protected $primaryTabs;
/**
* @var Backend\Classes\FormTabs Collection of fields inside the secondary tabs.
*/
protected $secondaryTabs;
/** /**
* @var string If the field element names should be contained in an array. * @var string If the field element names should be contained in an array.
@ -91,11 +64,40 @@ class Form extends WidgetBase
*/ */
public $arrayName; public $arrayName;
//
// Object properties
//
/** /**
* @var string The context of this form, fields that do not belong * {@inheritDoc}
* to this context will not be shown.
*/ */
protected $activeContext = null; protected $defaultAlias = 'form';
/**
* @var boolean Determines if field definitions have been created.
*/
protected $fieldsDefined = false;
/**
* @var array Collection of all fields used in this form.
* @see Backend\Classes\FormField
*/
protected $allFields = [];
/**
* @var object Collection of tab sections used in this form.
* @see Backend\Classes\FormTabs
*/
protected $allTabs = [
'outside' => null,
'primary' => null,
'secondary' => null,
];
/**
* @var array Collection of all form widgets used in this form.
*/
protected $formWidgets = [];
/** /**
* @var string Active session key, used for editing forms and deferred bindings. * @var string Active session key, used for editing forms and deferred bindings.
@ -117,9 +119,18 @@ class Form extends WidgetBase
*/ */
public function init() public function init()
{ {
$this->fillFromConfig([
'fields',
'tabs',
'secondaryTabs',
'model',
'data',
'arrayName',
'context',
]);
$this->widgetManager = WidgetManager::instance(); $this->widgetManager = WidgetManager::instance();
$this->arrayName = $this->getConfig('arrayName'); $this->allTabs = (object) $this->allTabs;
$this->activeContext = $this->getConfig('context');
$this->validateModel(); $this->validateModel();
} }
@ -174,17 +185,10 @@ class Form extends WidgetBase
* Determine the partial to use based on the supplied section option * Determine the partial to use based on the supplied section option
*/ */
if ($section = $options['section']) { if ($section = $options['section']) {
$section = strtolower($section);
switch (strtolower($section)) { if (isset($this->allTabs->{$section})) {
case 'outside': $extraVars['tabs'] = $this->allTabs->{$section};
$extraVars['tabs'] = $this->outsideTabs;
break;
case 'primary':
$extraVars['tabs'] = $this->primaryTabs;
break;
case 'secondary':
$extraVars['tabs'] = $this->secondaryTabs;
break;
} }
$targetPartial = 'section'; $targetPartial = 'section';
@ -208,14 +212,14 @@ class Form extends WidgetBase
public function renderField($field, $options = []) public function renderField($field, $options = [])
{ {
if (is_string($field)) { if (is_string($field)) {
if (!isset($this->fields[$field])) { if (!isset($this->allFields[$field])) {
throw new ApplicationException(Lang::get( throw new ApplicationException(Lang::get(
'backend::lang.form.missing_definition', 'backend::lang.form.missing_definition',
compact('field') compact('field')
)); ));
} }
$field = $this->fields[$field]; $field = $this->allFields[$field];
} }
if (!isset($options['useContainer'])) { if (!isset($options['useContainer'])) {
@ -241,8 +245,6 @@ class Form extends WidgetBase
*/ */
protected function validateModel() protected function validateModel()
{ {
$this->model = $this->getConfig('model');
if (!$this->model) { if (!$this->model) {
throw new ApplicationException(Lang::get( throw new ApplicationException(Lang::get(
'backend::lang.form.missing_model', 'backend::lang.form.missing_model',
@ -250,7 +252,9 @@ class Form extends WidgetBase
)); ));
} }
$this->data = (object) $this->getConfig('data', $this->model); $this->data = isset($this->data)
? (object) $this->data
: $this->model;
return $this->model; return $this->model;
} }
@ -263,9 +267,9 @@ class Form extends WidgetBase
$this->defineFormFields(); $this->defineFormFields();
$this->applyFiltersFromModel(); $this->applyFiltersFromModel();
$this->vars['sessionKey'] = $this->getSessionKey(); $this->vars['sessionKey'] = $this->getSessionKey();
$this->vars['outsideTabs'] = $this->outsideTabs; $this->vars['outsideTabs'] = $this->allTabs->outside;
$this->vars['primaryTabs'] = $this->primaryTabs; $this->vars['primaryTabs'] = $this->allTabs->primary;
$this->vars['secondaryTabs'] = $this->secondaryTabs; $this->vars['secondaryTabs'] = $this->allTabs->secondary;
} }
/** /**
@ -282,7 +286,7 @@ class Form extends WidgetBase
$this->model->fill($data); $this->model->fill($data);
$this->data = (object) array_merge((array) $this->data, (array) $data); $this->data = (object) array_merge((array) $this->data, (array) $data);
foreach ($this->fields as $field) { foreach ($this->allFields as $field) {
$field->value = $this->getFieldValue($field); $field->value = $this->getFieldValue($field);
} }
@ -316,8 +320,8 @@ class Form extends WidgetBase
/* /*
* Extensibility * Extensibility
*/ */
$this->fireEvent('form.refreshFields', [$this->fields]); $this->fireEvent('form.refreshFields', [$this->allFields]);
Event::fire('backend.form.refreshFields', [$this, $this->fields]); Event::fire('backend.form.refreshFields', [$this, $this->allFields]);
/* /*
* If an array of fields is supplied, update specified fields individually. * If an array of fields is supplied, update specified fields individually.
@ -325,11 +329,11 @@ class Form extends WidgetBase
if (($updateFields = post('fields')) && is_array($updateFields)) { if (($updateFields = post('fields')) && is_array($updateFields)) {
foreach ($updateFields as $field) { foreach ($updateFields as $field) {
if (!isset($this->fields[$field])) { if (!isset($this->allFields[$field])) {
continue; continue;
} }
$fieldObject = $this->fields[$field]; $fieldObject = $this->allFields[$field];
$result['#' . $fieldObject->getId('group')] = $this->makePartial('field', ['field' => $fieldObject]); $result['#' . $fieldObject->getId('group')] = $this->makePartial('field', ['field' => $fieldObject]);
} }
} }
@ -373,51 +377,51 @@ class Form extends WidgetBase
/* /*
* Outside fields * Outside fields
*/ */
if (!isset($this->config->fields) || !is_array($this->config->fields)) { if (!isset($this->fields) || !is_array($this->fields)) {
$this->config->fields = []; $this->fields = [];
} }
$this->outsideTabs = new FormTabs(FormTabs::SECTION_OUTSIDE, $this->config); $this->allTabs->outside = new FormTabs(FormTabs::SECTION_OUTSIDE, $this->config);
$this->addFields($this->config->fields); $this->addFields($this->fields);
/* /*
* Primary Tabs + Fields * Primary Tabs + Fields
*/ */
if (!isset($this->config->tabs['fields']) || !is_array($this->config->tabs['fields'])) { if (!isset($this->tabs['fields']) || !is_array($this->tabs['fields'])) {
$this->config->tabs['fields'] = []; $this->tabs['fields'] = [];
} }
$this->primaryTabs = new FormTabs(FormTabs::SECTION_PRIMARY, $this->config->tabs); $this->allTabs->primary = new FormTabs(FormTabs::SECTION_PRIMARY, $this->tabs);
$this->addFields($this->config->tabs['fields'], FormTabs::SECTION_PRIMARY); $this->addFields($this->tabs['fields'], FormTabs::SECTION_PRIMARY);
/* /*
* Secondary Tabs + Fields * Secondary Tabs + Fields
*/ */
if (!isset($this->config->secondaryTabs['fields']) || !is_array($this->config->secondaryTabs['fields'])) { if (!isset($this->secondaryTabs['fields']) || !is_array($this->secondaryTabs['fields'])) {
$this->config->secondaryTabs['fields'] = []; $this->secondaryTabs['fields'] = [];
} }
$this->secondaryTabs = new FormTabs(FormTabs::SECTION_SECONDARY, $this->config->secondaryTabs); $this->allTabs->secondary = new FormTabs(FormTabs::SECTION_SECONDARY, $this->secondaryTabs);
$this->addFields($this->config->secondaryTabs['fields'], FormTabs::SECTION_SECONDARY); $this->addFields($this->secondaryTabs['fields'], FormTabs::SECTION_SECONDARY);
/* /*
* Extensibility * Extensibility
*/ */
$this->fireEvent('form.extendFields', [$this->fields]); $this->fireEvent('form.extendFields', [$this->allFields]);
Event::fire('backend.form.extendFields', [$this, $this->fields]); Event::fire('backend.form.extendFields', [$this, $this->allFields]);
/* /*
* Convert automatic spanned fields * Convert automatic spanned fields
*/ */
foreach ($this->outsideTabs->getTabs() as $fields) { foreach ($this->allTabs->outside->getTabs() as $fields) {
$this->processAutoSpan($fields); $this->processAutoSpan($fields);
} }
foreach ($this->primaryTabs->getTabs() as $fields) { foreach ($this->allTabs->primary->getTabs() as $fields) {
$this->processAutoSpan($fields); $this->processAutoSpan($fields);
} }
foreach ($this->secondaryTabs->getTabs() as $fields) { foreach ($this->allTabs->secondary->getTabs() as $fields) {
$this->processAutoSpan($fields); $this->processAutoSpan($fields);
} }
@ -425,25 +429,25 @@ class Form extends WidgetBase
* At least one tab section should stretch * At least one tab section should stretch
*/ */
if ( if (
$this->secondaryTabs->stretch === null $this->allTabs->secondary->stretch === null
&& $this->primaryTabs->stretch === null && $this->allTabs->primary->stretch === null
&& $this->outsideTabs->stretch === null && $this->allTabs->outside->stretch === null
) { ) {
if ($this->secondaryTabs->hasFields()) { if ($this->allTabs->secondary->hasFields()) {
$this->secondaryTabs->stretch = true; $this->allTabs->secondary->stretch = true;
} }
elseif ($this->primaryTabs->hasFields()) { elseif ($this->allTabs->primary->hasFields()) {
$this->primaryTabs->stretch = true; $this->allTabs->primary->stretch = true;
} }
else { else {
$this->outsideTabs->stretch = true; $this->allTabs->outside->stretch = true;
} }
} }
/* /*
* Bind all form widgets to controller * Bind all form widgets to controller
*/ */
foreach ($this->fields as $field) { foreach ($this->allFields as $field) {
if ($field->type != 'widget') { if ($field->type != 'widget') {
continue; continue;
} }
@ -496,17 +500,17 @@ class Form extends WidgetBase
} }
} }
$this->fields[$name] = $fieldObj; $this->allFields[$name] = $fieldObj;
switch (strtolower($addToArea)) { switch (strtolower($addToArea)) {
case FormTabs::SECTION_PRIMARY: case FormTabs::SECTION_PRIMARY:
$this->primaryTabs->addField($name, $fieldObj, $fieldTab); $this->allTabs->primary->addField($name, $fieldObj, $fieldTab);
break; break;
case FormTabs::SECTION_SECONDARY: case FormTabs::SECTION_SECONDARY:
$this->secondaryTabs->addField($name, $fieldObj, $fieldTab); $this->allTabs->secondary->addField($name, $fieldObj, $fieldTab);
break; break;
default: default:
$this->outsideTabs->addField($name, $fieldObj, $fieldTab); $this->allTabs->outside->addField($name, $fieldObj, $fieldTab);
break; break;
} }
} }
@ -528,21 +532,21 @@ class Form extends WidgetBase
*/ */
public function removeField($name) public function removeField($name)
{ {
if (!isset($this->fields[$name])) { if (!isset($this->allFields[$name])) {
return false; return false;
} }
/* /*
* Remove from tabs * Remove from tabs
*/ */
$this->primaryTabs->removeField($name); $this->allTabs->primary->removeField($name);
$this->secondaryTabs->removeField($name); $this->allTabs->secondary->removeField($name);
$this->outsideTabs->removeField($name); $this->allTabs->outside->removeField($name);
/* /*
* Remove from main collection * Remove from main collection
*/ */
unset($this->fields[$name]); unset($this->allFields[$name]);
return true; return true;
} }
@ -714,7 +718,7 @@ class Form extends WidgetBase
*/ */
public function getFields() public function getFields()
{ {
return $this->fields; return $this->allFields;
} }
/** /**
@ -724,7 +728,7 @@ class Form extends WidgetBase
*/ */
public function getField($field) public function getField($field)
{ {
return $this->fields[$field]; return $this->allFields[$field];
} }
/** /**
@ -747,14 +751,14 @@ class Form extends WidgetBase
public function getFieldValue($field) public function getFieldValue($field)
{ {
if (is_string($field)) { if (is_string($field)) {
if (!isset($this->fields[$field])) { if (!isset($this->allFields[$field])) {
throw new ApplicationException(Lang::get( throw new ApplicationException(Lang::get(
'backend::lang.form.missing_definition', 'backend::lang.form.missing_definition',
compact('field') compact('field')
)); ));
} }
$field = $this->fields[$field]; $field = $this->allFields[$field];
} }
$defaultValue = (!$this->model->exists && $field->defaults !== '') $defaultValue = (!$this->model->exists && $field->defaults !== '')
@ -795,7 +799,7 @@ class Form extends WidgetBase
/* /*
* Number fields should be converted to integers * Number fields should be converted to integers
*/ */
foreach ($this->fields as $field) { foreach ($this->allFields as $field) {
if ($field->type != 'number') { if ($field->type != 'number') {
continue; continue;
} }
@ -827,7 +831,7 @@ class Form extends WidgetBase
* Handle fields that differ by fieldName and valueFrom * Handle fields that differ by fieldName and valueFrom
*/ */
$remappedFields = []; $remappedFields = [];
foreach ($this->fields as $field) { foreach ($this->allFields as $field) {
if ($field->fieldName == $field->valueFrom) { if ($field->fieldName == $field->valueFrom) {
continue; continue;
} }
@ -863,7 +867,7 @@ class Form extends WidgetBase
protected function applyFiltersFromModel() protected function applyFiltersFromModel()
{ {
if (method_exists($this->model, 'filterFields')) { if (method_exists($this->model, 'filterFields')) {
$this->model->filterFields((object) $this->fields, $this->getContext()); $this->model->filterFields((object) $this->allFields, $this->getContext());
} }
} }
@ -939,7 +943,7 @@ class Form extends WidgetBase
*/ */
public function getContext() public function getContext()
{ {
return $this->activeContext; return $this->context;
} }
/** /**