964 lines
26 KiB
PHP
Raw Normal View History

2014-05-14 23:24:20 +10:00
<?php namespace Backend\Widgets;
use App;
use Str;
use Lang;
use Input;
use Event;
2015-02-25 19:10:42 +11:00
use Form as FormHelper;
use Backend\Classes\FormTabs;
2014-05-14 23:24:20 +10:00
use Backend\Classes\FormField;
use Backend\Classes\WidgetBase;
use Backend\Classes\WidgetManager;
2015-01-28 18:03:35 +11:00
use ApplicationException;
use Backend\Classes\FormWidgetBase;
use October\Rain\Database\Model;
2014-05-14 23:24:20 +10:00
/**
* Form Widget
* Used for building back end forms and renders a form.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class Form extends WidgetBase
{
//
// Configurable properties
//
/**
* @var array Form field configuration.
*/
public $fields;
2014-05-14 23:24:20 +10:00
/**
* @var array Primary tab configuration.
2014-05-14 23:24:20 +10:00
*/
public $tabs;
/**
* @var array Secondary tab configuration.
*/
public $secondaryTabs;
2014-05-14 23:24:20 +10:00
/**
* @var Model Form model object.
*/
public $model;
/**
* @var array Dataset containing field values, if none supplied, model is used.
*/
public $data;
/**
* @var string The context of this form, fields that do not belong
* to this context will not be shown.
2014-05-14 23:24:20 +10:00
*/
public $context = null;
2014-05-14 23:24:20 +10:00
/**
* @var string If the field element names should be contained in an array.
* Eg: <input name="nameArray[fieldName]" />
2014-05-14 23:24:20 +10:00
*/
public $arrayName;
2014-05-14 23:24:20 +10:00
//
// Object properties
//
2014-05-14 23:24:20 +10:00
/**
* {@inheritDoc}
2014-05-14 23:24:20 +10:00
*/
protected $defaultAlias = 'form';
2014-05-14 23:24:20 +10:00
/**
* @var boolean Determines if field definitions have been created.
2014-05-14 23:24:20 +10:00
*/
protected $fieldsDefined = false;
2014-05-14 23:24:20 +10:00
/**
* @var array Collection of all fields used in this form.
* @see Backend\Classes\FormField
2014-05-14 23:24:20 +10:00
*/
protected $allFields = [];
2014-05-14 23:24:20 +10:00
/**
* @var object Collection of tab sections used in this form.
* @see Backend\Classes\FormTabs
2014-05-14 23:24:20 +10:00
*/
protected $allTabs = [
'outside' => null,
'primary' => null,
'secondary' => null,
];
2014-05-14 23:24:20 +10:00
/**
* @var array Collection of all form widgets used in this form.
2014-05-14 23:24:20 +10:00
*/
protected $formWidgets = [];
2014-05-14 23:24:20 +10:00
/**
* @var string Active session key, used for editing forms and deferred bindings.
*/
public $sessionKey;
/**
* @var bool Render this form with uneditable preview data.
*/
public $previewMode = false;
/**
* @var Backend\Classes\WidgetManager
*/
protected $widgetManager;
/**
* Initialize the widget, called by the constructor and free from its parameters.
*/
public function init()
{
$this->fillFromConfig([
'fields',
'tabs',
'secondaryTabs',
'model',
'data',
'arrayName',
'context',
]);
2014-05-14 23:24:20 +10:00
$this->widgetManager = WidgetManager::instance();
$this->allTabs = (object) $this->allTabs;
2014-05-14 23:24:20 +10:00
$this->validateModel();
}
/**
* Ensure fields are defined and form widgets are registered so they can
* also be bound to the controller this allows their AJAX features to
* operate.
* @return void
*/
public function bindToController()
{
$this->defineFormFields();
parent::bindToController();
}
/**
* {@inheritDoc}
*/
public function loadAssets()
{
$this->addJs('js/october.form.js', 'core');
2014-05-14 23:24:20 +10:00
}
/**
* Renders the widget.
*
* Options:
* - preview: Render this form as an uneditable preview. Default: false
* - useContainer: Wrap the result in a container, used by AJAX. Default: true
2014-05-14 23:24:20 +10:00
* - section: Which form section to render. Default: null
* - outside: Renders the Outside Fields section.
* - primary: Renders the Primary Tabs section.
* - secondary: Renders the Secondary Tabs section.
2014-05-14 23:24:20 +10:00
* - null: Renders all sections
*/
public function render($options = [])
{
2014-10-11 00:39:34 +02:00
if (isset($options['preview'])) {
$this->previewMode = $options['preview'];
}
if (!isset($options['useContainer'])) {
$options['useContainer'] = true;
}
if (!isset($options['section'])) {
$options['section'] = null;
}
$extraVars = [];
$targetPartial = 'form';
2014-05-14 23:24:20 +10:00
/*
* Determine the partial to use based on the supplied section option
*/
if ($section = $options['section']) {
$section = strtolower($section);
if (isset($this->allTabs->{$section})) {
$extraVars['tabs'] = $this->allTabs->{$section};
}
$targetPartial = 'section';
$extraVars['renderSection'] = $section;
}
/*
* Apply a container to the element
*/
if ($useContainer = $options['useContainer']) {
$targetPartial = ($section) ? 'section-container' : 'form-container';
2014-05-14 23:24:20 +10:00
}
$this->prepareVars();
return $this->makePartial($targetPartial, $extraVars);
2014-05-14 23:24:20 +10:00
}
/**
* Renders a single form field
*/
public function renderField($field, $options = [])
2014-05-14 23:24:20 +10:00
{
if (is_string($field)) {
if (!isset($this->allFields[$field])) {
2014-10-11 00:39:34 +02:00
throw new ApplicationException(Lang::get(
'backend::lang.form.missing_definition',
compact('field')
));
}
2014-05-14 23:24:20 +10:00
$field = $this->allFields[$field];
2014-05-14 23:24:20 +10:00
}
2014-10-11 00:39:34 +02:00
if (!isset($options['useContainer'])) {
$options['useContainer'] = true;
}
$targetPartial = $options['useContainer'] ? 'field-container' : 'field';
2014-05-14 23:24:20 +10:00
$this->prepareVars();
return $this->makePartial($targetPartial, ['field' => $field]);
2014-05-14 23:24:20 +10:00
}
/**
* Renders the HTML element for a field
*/
public function renderFieldElement($field)
{
return $this->makePartial('field_'.$field->type, ['field' => $field, 'formModel' => $this->model]);
2014-05-14 23:24:20 +10:00
}
/**
* Validate the supplied form model.
* @return void
*/
protected function validateModel()
{
2014-10-11 00:39:34 +02:00
if (!$this->model) {
throw new ApplicationException(Lang::get(
'backend::lang.form.missing_model',
['class'=>get_class($this->controller)]
));
}
2014-05-14 23:24:20 +10:00
$this->data = isset($this->data)
? (object) $this->data
: $this->model;
2014-05-14 23:24:20 +10:00
return $this->model;
}
/**
2014-10-11 10:37:48 +11:00
* Prepares the form data
2014-05-14 23:24:20 +10:00
*/
2014-08-01 18:18:09 +10:00
protected function prepareVars()
2014-05-14 23:24:20 +10:00
{
$this->defineFormFields();
$this->applyFiltersFromModel();
2014-05-14 23:24:20 +10:00
$this->vars['sessionKey'] = $this->getSessionKey();
$this->vars['outsideTabs'] = $this->allTabs->outside;
$this->vars['primaryTabs'] = $this->allTabs->primary;
$this->vars['secondaryTabs'] = $this->allTabs->secondary;
2014-05-14 23:24:20 +10:00
}
/**
* Sets or resets form field values.
* @param array $data
* @return array
*/
public function setFormValues($data = null)
{
2014-10-11 00:39:34 +02:00
if ($data == null) {
$data = $this->getSaveData();
2014-10-11 00:39:34 +02:00
}
$this->model->fill($data);
$this->data = (object) array_merge((array) $this->data, (array) $data);
foreach ($this->allFields as $field) {
$field->value = $this->getFieldValue($field);
2014-09-17 19:49:42 +10:00
}
return $data;
}
/**
* Event handler for refreshing the form.
*/
public function onRefresh()
{
$result = [];
$saveData = $this->getSaveData();
/*
* Extensibility
*/
2014-10-11 00:39:34 +02:00
$eventResults = $this->fireEvent('form.beforeRefresh', [$saveData]) +
Event::fire('backend.form.beforeRefresh', [$this, $saveData]);
2014-10-11 00:39:34 +02:00
foreach ($eventResults as $eventResult) {
$saveData = $eventResult + $saveData;
2014-10-11 00:39:34 +02:00
}
/*
* Set the form variables and prepare the widget
*/
$this->setFormValues($saveData);
$this->prepareVars();
/*
* Extensibility
*/
$this->fireEvent('form.refreshFields', [$this->allFields]);
Event::fire('backend.form.refreshFields', [$this, $this->allFields]);
/*
* If an array of fields is supplied, update specified fields individually.
*/
if (($updateFields = post('fields')) && is_array($updateFields)) {
foreach ($updateFields as $field) {
if (!isset($this->allFields[$field])) {
continue;
2014-10-11 00:39:34 +02:00
}
$fieldObject = $this->allFields[$field];
$result['#' . $fieldObject->getId('group')] = $this->makePartial('field', ['field' => $fieldObject]);
}
}
/*
* Update the whole form
*/
2014-10-11 00:39:34 +02:00
if (empty($result)) {
$result = ['#'.$this->getId() => $this->makePartial('form')];
2014-10-11 00:39:34 +02:00
}
/*
* Extensibility
*/
2014-10-11 00:39:34 +02:00
$eventResults = $this->fireEvent('form.refresh', [$result]) +
Event::fire('backend.form.refresh', [$this, $result]);
2014-10-11 00:39:34 +02:00
foreach ($eventResults as $eventResult) {
$result = $eventResult + $result;
2014-10-11 00:39:34 +02:00
}
return $result;
}
2014-05-14 23:24:20 +10:00
/**
* Creates a flat array of form fields from the configuration.
* Also slots fields in to their respective tabs.
*/
protected function defineFormFields()
{
2014-10-11 00:39:34 +02:00
if ($this->fieldsDefined) {
2014-05-14 23:24:20 +10:00
return;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Extensibility
*/
Event::fire('backend.form.extendFieldsBefore', [$this]);
$this->fireEvent('form.extendFieldsBefore');
2014-05-14 23:24:20 +10:00
/*
* Outside fields
*/
if (!isset($this->fields) || !is_array($this->fields)) {
$this->fields = [];
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$this->allTabs->outside = new FormTabs(FormTabs::SECTION_OUTSIDE, $this->config);
$this->addFields($this->fields);
2014-05-14 23:24:20 +10:00
/*
* Primary Tabs + Fields
*/
if (!isset($this->tabs['fields']) || !is_array($this->tabs['fields'])) {
$this->tabs['fields'] = [];
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$this->allTabs->primary = new FormTabs(FormTabs::SECTION_PRIMARY, $this->tabs);
$this->addFields($this->tabs['fields'], FormTabs::SECTION_PRIMARY);
2014-05-14 23:24:20 +10:00
/*
* Secondary Tabs + Fields
*/
if (!isset($this->secondaryTabs['fields']) || !is_array($this->secondaryTabs['fields'])) {
$this->secondaryTabs['fields'] = [];
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$this->allTabs->secondary = new FormTabs(FormTabs::SECTION_SECONDARY, $this->secondaryTabs);
$this->addFields($this->secondaryTabs['fields'], FormTabs::SECTION_SECONDARY);
2014-05-14 23:24:20 +10:00
/*
* Extensibility
*/
$this->fireEvent('form.extendFields', [$this->allFields]);
Event::fire('backend.form.extendFields', [$this, $this->allFields]);
2014-05-14 23:24:20 +10:00
/*
* Convert automatic spanned fields
*/
foreach ($this->allTabs->outside->getTabs() as $fields) {
$this->processAutoSpan($fields);
}
2014-05-14 23:24:20 +10:00
foreach ($this->allTabs->primary->getTabs() as $fields) {
2014-05-14 23:24:20 +10:00
$this->processAutoSpan($fields);
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
foreach ($this->allTabs->secondary->getTabs() as $fields) {
2014-05-14 23:24:20 +10:00
$this->processAutoSpan($fields);
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* At least one tab section should stretch
*/
if (
$this->allTabs->secondary->stretch === null
&& $this->allTabs->primary->stretch === null
&& $this->allTabs->outside->stretch === null
) {
if ($this->allTabs->secondary->hasFields()) {
$this->allTabs->secondary->stretch = true;
}
elseif ($this->allTabs->primary->hasFields()) {
$this->allTabs->primary->stretch = true;
}
else {
$this->allTabs->outside->stretch = true;
}
}
2014-05-14 23:24:20 +10:00
/*
* Bind all form widgets to controller
*/
foreach ($this->allFields as $field) {
2014-10-11 00:39:34 +02:00
if ($field->type != 'widget') {
2014-05-14 23:24:20 +10:00
continue;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$widget = $this->makeFormWidget($field);
$widget->bindToController();
}
$this->fieldsDefined = true;
}
/**
* Converts fields with a span set to 'auto' as either
* 'left' or 'right' depending on the previous field.
*/
protected function processAutoSpan($fields)
{
$prevSpan = null;
foreach ($fields as $field) {
if (strtolower($field->span) == 'auto') {
2014-10-11 00:39:34 +02:00
if ($prevSpan == 'left') {
2014-05-14 23:24:20 +10:00
$field->span = 'right';
2014-11-04 17:41:48 +11:00
}
else {
2014-05-14 23:24:20 +10:00
$field->span = 'left';
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
}
$prevSpan = $field->span;
}
}
/**
* Programatically add fields, used internally and for extensibility.
*/
2014-05-21 21:26:28 +10:00
public function addFields(array $fields, $addToArea = null)
2014-05-14 23:24:20 +10:00
{
foreach ($fields as $name => $config) {
$fieldObj = $this->makeFormField($name, $config);
$fieldTab = is_array($config) ? array_get($config, 'tab') : null;
2014-05-14 23:24:20 +10:00
/*
* Check that the form field matches the active context
*/
if ($fieldObj->context !== null) {
$context = (is_array($fieldObj->context)) ? $fieldObj->context : [$fieldObj->context];
2014-10-11 00:39:34 +02:00
if (!in_array($this->getContext(), $context)) {
2014-05-14 23:24:20 +10:00
continue;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
}
$this->allFields[$name] = $fieldObj;
2014-05-14 23:24:20 +10:00
2014-05-21 21:26:28 +10:00
switch (strtolower($addToArea)) {
case FormTabs::SECTION_PRIMARY:
$this->allTabs->primary->addField($name, $fieldObj, $fieldTab);
2014-05-14 23:24:20 +10:00
break;
case FormTabs::SECTION_SECONDARY:
$this->allTabs->secondary->addField($name, $fieldObj, $fieldTab);
2014-05-14 23:24:20 +10:00
break;
default:
$this->allTabs->outside->addField($name, $fieldObj, $fieldTab);
2014-05-14 23:24:20 +10:00
break;
}
}
}
public function addTabFields(array $fields)
{
return $this->addFields($fields, 'primary');
}
public function addSecondaryTabFields(array $fields)
{
return $this->addFields($fields, 'secondary');
}
2015-02-12 08:37:24 +11:00
/**
* Programatically remove a field.
* @return boolean
*/
public function removeField($name)
{
if (!isset($this->allFields[$name])) {
2015-02-12 08:37:24 +11:00
return false;
}
/*
* Remove from tabs
*/
$this->allTabs->primary->removeField($name);
$this->allTabs->secondary->removeField($name);
$this->allTabs->outside->removeField($name);
2015-02-12 08:37:24 +11:00
/*
* Remove from main collection
*/
unset($this->allFields[$name]);
2015-02-12 08:37:24 +11:00
return true;
}
2014-05-14 23:24:20 +10:00
/**
* Creates a form field object from name and configuration.
*/
protected function makeFormField($name, $config)
{
$label = (isset($config['label'])) ? $config['label'] : null;
list($fieldName, $fieldContext) = $this->getFieldName($name);
$field = new FormField($fieldName, $label);
2014-10-11 00:39:34 +02:00
if ($fieldContext) {
$field->context = $fieldContext;
}
2014-05-14 23:24:20 +10:00
$field->arrayName = $this->arrayName;
$field->idPrefix = $this->getId();
2014-06-08 18:07:56 +10:00
/*
* Simple field type
2014-06-08 18:07:56 +10:00
*/
if (is_string($config)) {
2014-10-19 10:58:18 +11:00
2014-10-11 00:39:34 +02:00
if ($this->isFormWidget($config) !== false) {
$field->displayAs('widget', ['widget' => $config]);
2014-11-04 17:41:48 +11:00
}
else {
$field->displayAs($config);
2014-10-11 00:39:34 +02:00
}
2014-10-19 10:58:18 +11:00
2014-11-04 17:41:48 +11:00
}
2014-06-08 18:08:54 +10:00
/*
* Defined field type
*/
2014-11-04 17:41:48 +11:00
else {
2014-10-19 10:58:18 +11:00
$fieldType = isset($config['type']) ? $config['type'] : null;
2014-10-11 00:39:34 +02:00
if (!is_string($fieldType) && !is_null($fieldType)) {
throw new ApplicationException(Lang::get(
'backend::lang.field.invalid_type',
['type'=>gettype($fieldType)]
));
}
/*
* Widget with configuration
*/
if ($this->isFormWidget($fieldType) !== false) {
$config['widget'] = $fieldType;
$fieldType = 'widget';
}
$field->displayAs($fieldType, $config);
2014-10-19 10:58:18 +11:00
}
/*
* Set field value
*/
$field->value = $this->getFieldValue($field);
/*
* Check model if field is required
*/
2014-10-11 00:39:34 +02:00
if (!$field->required && $this->model && method_exists($this->model, 'isAttributeRequired')) {
$field->required = $this->model->isAttributeRequired($field->fieldName);
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Get field options from model
2014-05-14 23:24:20 +10:00
*/
$optionModelTypes = ['dropdown', 'radio', 'checkboxlist', 'balloon-selector'];
if (in_array($field->type, $optionModelTypes)) {
/*
* Defer the execution of option data collection
*/
2014-10-11 00:39:34 +02:00
$field->options(function () use ($field, $config) {
$fieldOptions = (isset($config['options'])) ? $config['options'] : null;
$fieldOptions = $this->getOptionsFromModel($field, $fieldOptions);
return $fieldOptions;
});
2014-05-14 23:24:20 +10:00
}
return $field;
}
/**
* Check if a field type is a widget or not
* @param string $fieldType
* @return boolean
*/
2014-08-01 18:18:09 +10:00
protected function isFormWidget($fieldType)
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ($fieldType === null) {
2014-05-14 23:24:20 +10:00
return false;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if (strpos($fieldType, '\\')) {
2014-05-14 23:24:20 +10:00
return true;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$widgetClass = $this->widgetManager->resolveFormWidget($fieldType);
2014-10-11 00:39:34 +02:00
if (!class_exists($widgetClass)) {
2014-05-14 23:24:20 +10:00
return false;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if (is_subclass_of($widgetClass, 'Backend\Classes\FormWidgetBase')) {
2014-05-14 23:24:20 +10:00
return true;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
return false;
}
/**
* Makes a widget object from a form field object.
*/
2014-08-01 18:18:09 +10:00
protected function makeFormWidget($field)
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ($field->type != 'widget') {
2014-05-14 23:24:20 +10:00
return null;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if (isset($this->formWidgets[$field->fieldName])) {
return $this->formWidgets[$field->fieldName];
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$widgetConfig = $this->makeConfig($field->config);
$widgetConfig->alias = $this->alias . studly_case(Str::evalHtmlId($field->fieldName));
2014-05-14 23:24:20 +10:00
$widgetConfig->sessionKey = $this->getSessionKey();
$widgetName = $widgetConfig->widget;
$widgetClass = $this->widgetManager->resolveFormWidget($widgetName);
if (!class_exists($widgetClass)) {
2014-10-11 00:39:34 +02:00
throw new ApplicationException(Lang::get(
'backend::lang.widget.not_registered',
['name' => $widgetClass]
));
2014-05-14 23:24:20 +10:00
}
$widget = new $widgetClass($this->controller, $this->model, $field, $widgetConfig);
return $this->formWidgets[$field->fieldName] = $widget;
2014-05-14 23:24:20 +10:00
}
/**
* Get all the loaded form widgets for the instance.
* @return array
*/
public function getFormWidgets()
{
return $this->formWidgets;
}
/**
* Get a specified form widget
* @param string $fieldName
* @return mixed
*/
public function getFormWidget($field)
{
return $this->formWidgets[$field];
}
/**
* Get all the registered fields for the instance.
* @return array
*/
public function getFields()
{
return $this->allFields;
}
/**
* Get a specified field object
* @param string $fieldName
* @return mixed
*/
public function getField($field)
{
return $this->allFields[$field];
}
/**
* Parses a field's name
* @param string $field Field name
* @return array [columnName, context]
*/
public function getFieldName($field)
{
2014-10-11 00:39:34 +02:00
if (strpos($field, '@') === false) {
return [$field, null];
2014-10-11 00:39:34 +02:00
}
return explode('@', $field);
}
2014-05-14 23:24:20 +10:00
/**
* Looks up the column
*/
public function getFieldValue($field)
{
if (is_string($field)) {
if (!isset($this->allFields[$field])) {
2014-10-11 00:39:34 +02:00
throw new ApplicationException(Lang::get(
'backend::lang.form.missing_definition',
compact('field')
));
}
2014-05-14 23:24:20 +10:00
$field = $this->allFields[$field];
2014-05-14 23:24:20 +10:00
}
2015-01-05 09:43:39 +11:00
$defaultValue = (!$this->model->exists && $field->defaults !== '')
? $field->defaults
: null;
2014-05-14 23:24:20 +10:00
return $field->getValueFromData($this->data, $defaultValue);
2014-05-14 23:24:20 +10:00
}
/**
* Returns a HTML encoded value containing the other fields this
* field depends on
* @param use Backend\Classes\FormField $field
* @return string
*/
public function getFieldDepends($field)
{
if (!$field->dependsOn) {
return;
2014-10-11 00:39:34 +02:00
}
$dependsOn = is_array($field->dependsOn) ? $field->dependsOn : [$field->dependsOn];
$dependsOn = htmlspecialchars(json_encode($dependsOn), ENT_QUOTES, 'UTF-8');
return $dependsOn;
}
2014-05-14 23:24:20 +10:00
/**
* Returns postback data from a submitted form.
*/
public function getSaveData()
{
$data = ($this->arrayName) ? post($this->arrayName) : post();
2014-10-11 00:39:34 +02:00
if (!$data) {
2014-05-14 23:24:20 +10:00
$data = [];
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Number fields should be converted to integers
2014-05-14 23:24:20 +10:00
*/
foreach ($this->allFields as $field) {
2014-10-11 12:15:02 +02:00
if ($field->type != 'number') {
2014-05-14 23:24:20 +10:00
continue;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Handle HTML array, eg: item[key][another]
*/
$parts = Str::evalHtmlArray($field->fieldName);
$dotted = implode('.', $parts);
if (($value = array_get($data, $dotted)) !== null) {
$value = !strlen(trim($value)) ? null : (float) $value;
array_set($data, $dotted, $value);
}
2014-05-14 23:24:20 +10:00
}
/*
* Give widgets an opportunity to process the data.
*/
foreach ($this->formWidgets as $field => $widget) {
$parts = Str::evalHtmlArray($field);
$dotted = implode('.', $parts);
2014-05-14 23:24:20 +10:00
2015-01-05 09:43:39 +11:00
$widgetValue = $widget->getSaveValue(array_get($data, $dotted));
array_set($data, $dotted, $widgetValue);
2014-05-14 23:24:20 +10:00
}
/*
* Handle fields that differ by fieldName and valueFrom
*/
2014-09-17 20:18:37 +10:00
$remappedFields = [];
foreach ($this->allFields as $field) {
2014-10-11 00:39:34 +02:00
if ($field->fieldName == $field->valueFrom) {
continue;
2014-10-11 00:39:34 +02:00
}
/*
* Get the value, remove it from the data collection
*/
$parts = Str::evalHtmlArray($field->fieldName);
$dotted = implode('.', $parts);
$value = array_get($data, $dotted);
array_forget($data, $dotted);
/*
* Set the new value to the data collection
*/
$parts = Str::evalHtmlArray($field->valueFrom);
$dotted = implode('.', $parts);
2014-09-17 20:18:37 +10:00
array_set($remappedFields, $dotted, $value);
}
2014-09-17 20:18:37 +10:00
if (count($remappedFields) > 0) {
$data = array_merge($remappedFields, $data);
2014-09-18 08:22:22 +10:00
// Could be useful one day for field name collisions
2014-09-17 20:18:37 +10:00
// $data['X_OCTOBER_REMAPPED_FIELDS'] = $remappedFields;
}
2014-05-14 23:24:20 +10:00
return $data;
}
/*
* Allow the model to filter fields.
*/
protected function applyFiltersFromModel()
{
if (method_exists($this->model, 'filterFields')) {
$this->model->filterFields((object) $this->allFields, $this->getContext());
}
}
2014-05-14 23:24:20 +10:00
/**
* Looks at the model for defined options.
*/
2014-08-01 18:18:09 +10:00
protected function getOptionsFromModel($field, $fieldOptions)
2014-05-14 23:24:20 +10:00
{
/*
* Advanced usage, supplied options are callable
*/
if (is_array($fieldOptions) && is_callable($fieldOptions)) {
2014-06-01 10:23:59 +10:00
$fieldOptions = call_user_func($fieldOptions, $this, $field);
}
2014-06-01 10:23:59 +10:00
/*
* Refer to the model method or any of its behaviors
*/
2014-06-01 10:23:59 +10:00
if (!is_array($fieldOptions) && !$fieldOptions) {
$methodName = 'get'.studly_case($field->fieldName).'Options';
2014-10-11 00:39:34 +02:00
if (
!$this->methodExists($this->model, $methodName) &&
!$this->methodExists($this->model, 'getDropdownOptions')
) {
throw new ApplicationException(Lang::get(
'backend::lang.field.options_method_not_exists',
['model'=>get_class($this->model), 'method'=>$methodName, 'field'=>$field->fieldName]
));
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if ($this->methodExists($this->model, $methodName)) {
$fieldOptions = $this->model->$methodName($field->value);
2014-11-04 17:41:48 +11:00
}
else {
$fieldOptions = $this->model->getDropdownOptions($field->fieldName, $field->value);
2014-10-11 00:39:34 +02:00
}
2014-11-04 17:41:48 +11:00
}
/*
* Field options are an explicit method reference
*/
2014-11-04 17:41:48 +11:00
elseif (is_string($fieldOptions)) {
2014-10-11 00:39:34 +02:00
if (!$this->methodExists($this->model, $fieldOptions)) {
throw new ApplicationException(Lang::get(
'backend::lang.field.options_method_not_exists',
['model'=>get_class($this->model), 'method'=>$fieldOptions, 'field'=>$field->fieldName]
));
}
2014-05-14 23:24:20 +10:00
$fieldOptions = $this->model->$fieldOptions($field->value, $field->fieldName);
2014-05-14 23:24:20 +10:00
}
2014-06-01 10:23:59 +10:00
return $fieldOptions;
2014-05-14 23:24:20 +10:00
}
/**
* Returns the active session key.
*/
public function getSessionKey()
{
2014-10-11 00:39:34 +02:00
if ($this->sessionKey) {
2014-05-14 23:24:20 +10:00
return $this->sessionKey;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if (post('_session_key')) {
2014-05-14 23:24:20 +10:00
return $this->sessionKey = post('_session_key');
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
return $this->sessionKey = FormHelper::getSessionKey();
}
/**
* Returns the active context for displaying the form.
*/
public function getContext()
{
return $this->context;
2014-05-14 23:24:20 +10:00
}
2014-06-16 22:22:31 +10:00
/**
* Internal helper for method existence checks
* @param object $object
* @param string $method
* @return boolean
*/
2014-08-01 18:18:09 +10:00
protected function methodExists($object, $method)
2014-06-16 22:22:31 +10:00
{
2014-10-11 00:39:34 +02:00
if (method_exists($object, 'methodExists')) {
2014-06-16 22:22:31 +10:00
return $object->methodExists($method);
2014-10-11 00:39:34 +02:00
}
2014-06-16 22:22:31 +10:00
return method_exists($object, $method);
}
2014-09-13 17:17:15 +10:00
}