2014-05-14 23:24:20 +10:00
|
|
|
<?php namespace Backend\Widgets;
|
|
|
|
|
2016-02-13 13:18:48 +11:00
|
|
|
use Lang;
|
|
|
|
use Event;
|
|
|
|
use Form as FormHelper;
|
2016-01-15 21:57:47 +01:00
|
|
|
use Backend\Classes\FormTabs;
|
2016-02-13 13:18:48 +11:00
|
|
|
use Backend\Classes\FormField;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Backend\Classes\WidgetBase;
|
|
|
|
use Backend\Classes\WidgetManager;
|
2016-02-13 13:18:48 +11:00
|
|
|
use Backend\Classes\FormWidgetBase;
|
2014-10-11 12:13:25 +11:00
|
|
|
use October\Rain\Database\Model;
|
2015-03-07 12:48:39 +11:00
|
|
|
use October\Rain\Html\Helper as HtmlHelper;
|
2016-02-13 13:18:48 +11:00
|
|
|
use ApplicationException;
|
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
|
|
|
|
{
|
2015-02-28 13:37:06 +11:00
|
|
|
//
|
|
|
|
// Configurable properties
|
|
|
|
//
|
|
|
|
|
2015-02-28 11:50:27 +11:00
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @var array Form field configuration.
|
|
|
|
*/
|
|
|
|
public $fields;
|
2015-02-28 11:50:27 +11:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @var array Primary tab configuration.
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11: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;
|
|
|
|
|
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @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
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
public $context = null;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 13:37:06 +11: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
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
public $arrayName;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-02-28 13:37:06 +11:00
|
|
|
//
|
|
|
|
// Object properties
|
|
|
|
//
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2016-02-13 13:18:48 +11:00
|
|
|
* {@inheritDoc}
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
protected $defaultAlias = 'form';
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @var boolean Determines if field definitions have been created.
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
protected $fieldsDefined = false;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @var array Collection of all fields used in this form.
|
|
|
|
* @see Backend\Classes\FormField
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
protected $allFields = [];
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @var object Collection of tab sections used in this form.
|
|
|
|
* @see Backend\Classes\FormTabs
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
protected $allTabs = [
|
|
|
|
'outside' => null,
|
|
|
|
'primary' => null,
|
|
|
|
'secondary' => null,
|
|
|
|
];
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 13:37:06 +11:00
|
|
|
* @var array Collection of all form widgets used in this form.
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11: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;
|
|
|
|
|
|
|
|
/**
|
2016-02-13 13:18:48 +11:00
|
|
|
* {@inheritDoc}
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
public function init()
|
|
|
|
{
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->fillFromConfig([
|
|
|
|
'fields',
|
|
|
|
'tabs',
|
|
|
|
'secondaryTabs',
|
|
|
|
'model',
|
|
|
|
'data',
|
|
|
|
'arrayName',
|
|
|
|
'context',
|
|
|
|
]);
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
$this->widgetManager = WidgetManager::instance();
|
2015-02-28 13:37:06 +11:00
|
|
|
$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.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
2014-05-14 23:24:20 +10:00
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function bindToController()
|
|
|
|
{
|
|
|
|
$this->defineFormFields();
|
|
|
|
parent::bindToController();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-02-13 13:18:48 +11:00
|
|
|
* {@inheritDoc}
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-08-04 19:32:51 +10:00
|
|
|
protected function loadAssets()
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
2014-06-29 13:35:47 +10:00
|
|
|
$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
|
2014-06-30 18:23:02 +10:00
|
|
|
* - 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
|
2014-11-12 07:33:58 +11:00
|
|
|
* - 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
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param array $options
|
|
|
|
* @return mixed
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
2014-06-30 18:23:02 +10:00
|
|
|
|
|
|
|
$extraVars = [];
|
|
|
|
$targetPartial = 'form';
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine the partial to use based on the supplied section option
|
|
|
|
*/
|
2014-06-30 18:23:02 +10:00
|
|
|
if ($section = $options['section']) {
|
2015-02-28 13:37:06 +11:00
|
|
|
$section = strtolower($section);
|
2014-06-30 18:23:02 +10:00
|
|
|
|
2015-02-28 13:37:06 +11:00
|
|
|
if (isset($this->allTabs->{$section})) {
|
|
|
|
$extraVars['tabs'] = $this->allTabs->{$section};
|
2014-06-30 18:23:02 +10:00
|
|
|
}
|
|
|
|
|
2014-11-12 07:33:58 +11:00
|
|
|
$targetPartial = 'section';
|
2014-06-30 18:23:02 +10:00
|
|
|
$extraVars['renderSection'] = $section;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Apply a container to the element
|
|
|
|
*/
|
|
|
|
if ($useContainer = $options['useContainer']) {
|
2016-01-15 21:57:47 +01:00
|
|
|
$targetPartial = $section ? 'section-container' : 'form-container';
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
$this->prepareVars();
|
2015-03-18 19:28:14 +11:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Apply preview mode to widgets
|
|
|
|
*/
|
|
|
|
foreach ($this->formWidgets as $widget) {
|
|
|
|
$widget->previewMode = $this->previewMode;
|
|
|
|
}
|
|
|
|
|
2014-06-30 18:23:02 +10:00
|
|
|
return $this->makePartial($targetPartial, $extraVars);
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a single form field
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param string $field
|
|
|
|
* @param array $options
|
|
|
|
* @return mixed
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2016-02-13 13:18:48 +11:00
|
|
|
public function renderField($field, $options = [])
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
|
|
|
if (is_string($field)) {
|
2015-02-28 13:37:06 +11:00
|
|
|
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
|
|
|
|
2015-02-28 13:37:06 +11: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;
|
|
|
|
}
|
2014-06-30 18:23:02 +10:00
|
|
|
$targetPartial = $options['useContainer'] ? 'field-container' : 'field';
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
$this->prepareVars();
|
2014-06-30 18:23:02 +10:00
|
|
|
return $this->makePartial($targetPartial, ['field' => $field]);
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders the HTML element for a field
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param $field
|
|
|
|
* @return mixed
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
public function renderFieldElement($field)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
return $this->makePartial(
|
|
|
|
'field_' . $field->type,
|
|
|
|
[
|
|
|
|
'field' => $field,
|
|
|
|
'formModel' => $this->model
|
|
|
|
]
|
|
|
|
);
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Validate the supplied form model.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return mixed
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
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
|
|
|
|
2015-02-28 13:37:06 +11: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
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return void
|
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();
|
2015-02-17 20:58:38 +11:00
|
|
|
$this->applyFiltersFromModel();
|
2014-05-14 23:24:20 +10:00
|
|
|
$this->vars['sessionKey'] = $this->getSessionKey();
|
2015-02-28 13:37:06 +11:00
|
|
|
$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
|
|
|
}
|
|
|
|
|
2014-06-29 13:35:47 +10:00
|
|
|
/**
|
|
|
|
* Sets or resets form field values.
|
|
|
|
* @param array $data
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function setFormValues($data = null)
|
|
|
|
{
|
2015-07-18 08:50:31 +10:00
|
|
|
if ($data === null) {
|
2014-06-29 13:35:47 +10:00
|
|
|
$data = $this->getSaveData();
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-06-29 13:35:47 +10:00
|
|
|
|
2015-10-17 11:40:07 +11:00
|
|
|
$this->model->forceFill($data);
|
2014-06-29 13:35:47 +10:00
|
|
|
$this->data = (object) array_merge((array) $this->data, (array) $data);
|
|
|
|
|
2015-02-28 13:37:06 +11:00
|
|
|
foreach ($this->allFields as $field) {
|
2014-06-29 13:35:47 +10:00
|
|
|
$field->value = $this->getFieldValue($field);
|
2014-09-17 19:49:42 +10:00
|
|
|
}
|
2014-06-29 13:35:47 +10:00
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Event handler for refreshing the form.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return array
|
2014-06-29 13:35:47 +10:00
|
|
|
*/
|
2014-07-03 18:35:35 +10:00
|
|
|
public function onRefresh()
|
2014-06-29 13:35:47 +10:00
|
|
|
{
|
|
|
|
$result = [];
|
2014-07-03 18:35:35 +10:00
|
|
|
$saveData = $this->getSaveData();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Extensibility
|
|
|
|
*/
|
2015-07-18 08:50:31 +10:00
|
|
|
$dataHolder = (object) ['data' => $saveData];
|
|
|
|
$this->fireEvent('form.beforeRefresh', [$dataHolder]);
|
|
|
|
Event::fire('backend.form.beforeRefresh', [$this, $dataHolder]);
|
|
|
|
$saveData = $dataHolder->data;
|
2014-07-03 18:35:35 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the form variables and prepare the widget
|
|
|
|
*/
|
|
|
|
$this->setFormValues($saveData);
|
|
|
|
$this->prepareVars();
|
|
|
|
|
2015-01-29 20:32:24 +11:00
|
|
|
/*
|
|
|
|
* Extensibility
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->fireEvent('form.refreshFields', [$this->allFields]);
|
|
|
|
Event::fire('backend.form.refreshFields', [$this, $this->allFields]);
|
2015-01-29 20:32:24 +11:00
|
|
|
|
2014-06-29 13:35:47 +10:00
|
|
|
/*
|
|
|
|
* If an array of fields is supplied, update specified fields individually.
|
|
|
|
*/
|
|
|
|
if (($updateFields = post('fields')) && is_array($updateFields)) {
|
|
|
|
|
|
|
|
foreach ($updateFields as $field) {
|
2015-02-28 13:37:06 +11:00
|
|
|
if (!isset($this->allFields[$field])) {
|
2014-06-29 13:35:47 +10:00
|
|
|
continue;
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-06-29 13:35:47 +10:00
|
|
|
|
2015-02-28 13:37:06 +11:00
|
|
|
$fieldObject = $this->allFields[$field];
|
2014-07-03 18:35:35 +10:00
|
|
|
$result['#' . $fieldObject->getId('group')] = $this->makePartial('field', ['field' => $fieldObject]);
|
2014-06-29 13:35:47 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the whole form
|
|
|
|
*/
|
2014-10-11 00:39:34 +02:00
|
|
|
if (empty($result)) {
|
2014-06-29 13:35:47 +10:00
|
|
|
$result = ['#'.$this->getId() => $this->makePartial('form')];
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-06-29 13:35:47 +10:00
|
|
|
|
2014-07-03 18:35:35 +10:00
|
|
|
/*
|
|
|
|
* Extensibility
|
|
|
|
*/
|
2015-07-18 08:50:31 +10:00
|
|
|
$eventResults = array_merge(
|
|
|
|
$this->fireEvent('form.refresh', [$result]),
|
|
|
|
Event::fire('backend.form.refresh', [$this, $result])
|
|
|
|
);
|
2015-01-29 20:32:24 +11:00
|
|
|
|
2014-10-11 00:39:34 +02:00
|
|
|
foreach ($eventResults as $eventResult) {
|
2014-07-03 18:35:35 +10:00
|
|
|
$result = $eventResult + $result;
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-07-03 18:35:35 +10:00
|
|
|
|
2014-06-29 13:35:47 +10: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.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return void
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
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]);
|
2014-07-04 18:20:26 +10:00
|
|
|
$this->fireEvent('form.extendFieldsBefore');
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Outside fields
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
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
|
|
|
|
2015-02-28 13:37:06 +11: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
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
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
|
|
|
|
2015-02-28 13:37:06 +11: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
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
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
|
|
|
|
2015-02-28 13:37:06 +11: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
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
$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
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
foreach ($this->allTabs->outside->getTabs() as $fields) {
|
2014-11-12 07:33:58 +11:00
|
|
|
$this->processAutoSpan($fields);
|
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-02-28 13:37:06 +11: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
|
|
|
|
2015-02-28 13:37:06 +11: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
|
|
|
|
2014-11-12 07:33:58 +11:00
|
|
|
/*
|
|
|
|
* At least one tab section should stretch
|
|
|
|
*/
|
|
|
|
if (
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->allTabs->secondary->stretch === null
|
|
|
|
&& $this->allTabs->primary->stretch === null
|
|
|
|
&& $this->allTabs->outside->stretch === null
|
2014-11-12 07:33:58 +11:00
|
|
|
) {
|
2015-02-28 13:37:06 +11:00
|
|
|
if ($this->allTabs->secondary->hasFields()) {
|
|
|
|
$this->allTabs->secondary->stretch = true;
|
2014-11-12 07:33:58 +11:00
|
|
|
}
|
2015-02-28 13:37:06 +11:00
|
|
|
elseif ($this->allTabs->primary->hasFields()) {
|
|
|
|
$this->allTabs->primary->stretch = true;
|
2014-11-12 07:33:58 +11:00
|
|
|
}
|
|
|
|
else {
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->allTabs->outside->stretch = true;
|
2014-11-12 07:33:58 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
|
|
|
* Bind all form widgets to controller
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
foreach ($this->allFields as $field) {
|
2016-02-13 13:18:48 +11: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
|
|
|
|
2015-08-07 19:06:04 +10:00
|
|
|
$widget = $this->makeFormFieldWidget($field);
|
2014-05-14 23:24:20 +10:00
|
|
|
$widget->bindToController();
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->fieldsDefined = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts fields with a span set to 'auto' as either
|
|
|
|
* 'left' or 'right' depending on the previous field.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return void
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
protected function processAutoSpan($fields)
|
|
|
|
{
|
|
|
|
$prevSpan = null;
|
2016-01-15 21:57:47 +01:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
foreach ($fields as $field) {
|
2016-01-15 21:57:47 +01:00
|
|
|
if (strtolower($field->span) === 'auto') {
|
|
|
|
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.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param array $fields
|
2016-02-13 13:18:48 +11:00
|
|
|
* @param string $addToArea
|
|
|
|
* @return void
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
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);
|
2014-11-12 07:33:58 +11:00
|
|
|
$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
|
|
|
}
|
|
|
|
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->allFields[$name] = $fieldObj;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2014-05-21 21:26:28 +10:00
|
|
|
switch (strtolower($addToArea)) {
|
2014-11-12 07:33:58 +11:00
|
|
|
case FormTabs::SECTION_PRIMARY:
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->allTabs->primary->addField($name, $fieldObj, $fieldTab);
|
2014-05-14 23:24:20 +10:00
|
|
|
break;
|
2014-11-12 07:33:58 +11:00
|
|
|
case FormTabs::SECTION_SECONDARY:
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->allTabs->secondary->addField($name, $fieldObj, $fieldTab);
|
2014-05-14 23:24:20 +10:00
|
|
|
break;
|
|
|
|
default:
|
2015-05-21 22:51:35 +10:00
|
|
|
$this->allTabs->outside->addField($name, $fieldObj);
|
2014-05-14 23:24:20 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-15 21:57:47 +01:00
|
|
|
/**
|
|
|
|
* Add tab fields.
|
|
|
|
*
|
|
|
|
* @param array $fields
|
|
|
|
* @return void
|
|
|
|
*/
|
2014-05-14 23:24:20 +10:00
|
|
|
public function addTabFields(array $fields)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
$this->addFields($fields, 'primary');
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2016-01-15 21:57:47 +01:00
|
|
|
/**
|
|
|
|
* @param array $fields
|
|
|
|
* @return void
|
|
|
|
*/
|
2014-05-14 23:24:20 +10:00
|
|
|
public function addSecondaryTabFields(array $fields)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
$this->addFields($fields, 'secondary');
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2015-02-12 08:37:24 +11:00
|
|
|
/**
|
|
|
|
* Programatically remove a field.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @return bool
|
2015-02-12 08:37:24 +11:00
|
|
|
*/
|
|
|
|
public function removeField($name)
|
|
|
|
{
|
2015-02-28 13:37:06 +11:00
|
|
|
if (!isset($this->allFields[$name])) {
|
2015-02-12 08:37:24 +11:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove from tabs
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
$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
|
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
unset($this->allFields[$name]);
|
2015-02-12 08:37:24 +11:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-01-15 21:57:47 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* Creates a form field object from name and configuration.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @param array $config
|
|
|
|
* @return FormField
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2016-01-15 21:57:47 +01:00
|
|
|
protected function makeFormField($name, $config = [])
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
|
|
|
$label = (isset($config['label'])) ? $config['label'] : null;
|
2014-06-10 19:30:06 +10:00
|
|
|
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
|
|
|
/*
|
2014-06-19 21:40:24 +10:00
|
|
|
* Simple field type
|
2014-06-08 18:07:56 +10:00
|
|
|
*/
|
2014-06-19 21:40:24 +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) {
|
2014-06-19 21:40:24 +10:00
|
|
|
$field->displayAs('widget', ['widget' => $config]);
|
2014-11-04 17:41:48 +11:00
|
|
|
}
|
|
|
|
else {
|
2014-06-19 21:40:24 +10:00
|
|
|
$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
|
|
|
|
2014-06-19 21:40:24 +10: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)]
|
|
|
|
));
|
|
|
|
}
|
2014-06-19 21:40:24 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
2014-06-19 21:40:24 +10:00
|
|
|
}
|
2014-06-08 10:58:39 +10:00
|
|
|
|
2014-05-31 10:40:11 +10:00
|
|
|
/*
|
|
|
|
* Set field value
|
|
|
|
*/
|
|
|
|
$field->value = $this->getFieldValue($field);
|
|
|
|
|
2014-07-12 16:56:26 +10:00
|
|
|
/*
|
|
|
|
* Check model if field is required
|
|
|
|
*/
|
2014-10-11 00:39:34 +02:00
|
|
|
if (!$field->required && $this->model && method_exists($this->model, 'isAttributeRequired')) {
|
2014-09-17 19:20:44 +10:00
|
|
|
$field->required = $this->model->isAttributeRequired($field->fieldName);
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-07-12 16:56:26 +10:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
2014-06-19 21:40:24 +10:00
|
|
|
* Get field options from model
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2014-09-13 21:43:43 +10:00
|
|
|
$optionModelTypes = ['dropdown', 'radio', 'checkboxlist', 'balloon-selector'];
|
2016-01-15 21:57:47 +01:00
|
|
|
if (in_array($field->type, $optionModelTypes, false)) {
|
2014-06-29 13:35:47 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Defer the execution of option data collection
|
|
|
|
*/
|
2014-10-11 00:39:34 +02:00
|
|
|
$field->options(function () use ($field, $config) {
|
2014-06-29 13:35:47 +10:00
|
|
|
$fieldOptions = (isset($config['options'])) ? $config['options'] : null;
|
|
|
|
$fieldOptions = $this->getOptionsFromModel($field, $fieldOptions);
|
|
|
|
return $fieldOptions;
|
|
|
|
});
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
2014-06-29 13:35:47 +10:00
|
|
|
/**
|
|
|
|
* Check if a field type is a widget or not
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
2014-06-29 13:35:47 +10:00
|
|
|
* @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.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param $field
|
|
|
|
* @return \Backend\Traits\FormWidgetBase|null
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-08-07 19:06:04 +10:00
|
|
|
protected function makeFormFieldWidget($field)
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
2016-01-15 21:57:47 +01: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])) {
|
2014-09-17 19:20:44 +10:00
|
|
|
return $this->formWidgets[$field->fieldName];
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2014-06-19 21:40:24 +10:00
|
|
|
$widgetConfig = $this->makeConfig($field->config);
|
2015-03-07 12:48:39 +11:00
|
|
|
$widgetConfig->alias = $this->alias . studly_case(HtmlHelper::nameToId($field->fieldName));
|
2014-05-14 23:24:20 +10:00
|
|
|
$widgetConfig->sessionKey = $this->getSessionKey();
|
2015-03-06 20:37:05 +11:00
|
|
|
$widgetConfig->previewMode = $this->previewMode;
|
|
|
|
$widgetConfig->model = $this->model;
|
|
|
|
$widgetConfig->data = $this->data;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
$widgetName = $widgetConfig->widget;
|
|
|
|
$widgetClass = $this->widgetManager->resolveFormWidget($widgetName);
|
2016-01-15 21:57:47 +01:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-08-07 19:06:04 +10:00
|
|
|
$widget = $this->makeFormWidget($widgetClass, $field, $widgetConfig);
|
2015-03-03 18:38:36 +11:00
|
|
|
|
2014-09-17 19:20:44 +10:00
|
|
|
return $this->formWidgets[$field->fieldName] = $widget;
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2014-08-03 10:18:42 +10:00
|
|
|
/**
|
|
|
|
* Get all the loaded form widgets for the instance.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
2014-08-03 10:18:42 +10:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getFormWidgets()
|
|
|
|
{
|
|
|
|
return $this->formWidgets;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a specified form widget
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param string $field
|
2014-08-03 10:18:42 +10:00
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getFormWidget($field)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
if (isset($this->formWidgets[$field])) {
|
2016-02-13 13:18:48 +11:00
|
|
|
return $this->formWidgets[$field];
|
|
|
|
}
|
2014-08-03 10:18:42 +10:00
|
|
|
|
2016-01-15 21:57:47 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2014-08-03 10:18:42 +10:00
|
|
|
/**
|
|
|
|
* Get all the registered fields for the instance.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
2014-08-03 10:18:42 +10:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getFields()
|
|
|
|
{
|
2015-02-28 13:37:06 +11:00
|
|
|
return $this->allFields;
|
2014-08-03 10:18:42 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a specified field object
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param string $field
|
2014-08-03 10:18:42 +10:00
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
public function getField($field)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
if (isset($this->allFields[$field])) {
|
2016-02-13 13:18:48 +11:00
|
|
|
return $this->allFields[$field];
|
|
|
|
}
|
2014-08-03 10:18:42 +10:00
|
|
|
|
2016-01-15 21:57:47 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2014-06-10 19:30:06 +10:00
|
|
|
/**
|
|
|
|
* Parses a field's name
|
2015-02-21 19:55:37 +01:00
|
|
|
* @param string $field Field name
|
2014-06-10 19:30:06 +10:00
|
|
|
* @return array [columnName, context]
|
|
|
|
*/
|
2015-03-03 20:24:14 +11:00
|
|
|
protected function getFieldName($field)
|
2014-06-10 19:30:06 +10:00
|
|
|
{
|
2014-10-11 00:39:34 +02:00
|
|
|
if (strpos($field, '@') === false) {
|
2014-06-10 19:30:06 +10:00
|
|
|
return [$field, null];
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-06-10 19:30:06 +10:00
|
|
|
|
|
|
|
return explode('@', $field);
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
2015-03-03 20:24:14 +11:00
|
|
|
* Looks up the field value.
|
2016-01-15 21:57:47 +01:00
|
|
|
* @param mixed $field
|
2015-03-03 20:24:14 +11:00
|
|
|
* @return string
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-03-03 20:24:14 +11:00
|
|
|
protected function getFieldValue($field)
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
|
|
|
if (is_string($field)) {
|
2015-02-28 13:37:06 +11:00
|
|
|
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
|
|
|
|
2015-02-28 13:37:06 +11:00
|
|
|
$field = $this->allFields[$field];
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2015-10-17 10:16:49 +11:00
|
|
|
$defaultValue = !$this->model->exists
|
|
|
|
? $field->getDefaultFromData($this->data)
|
|
|
|
: null;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-01-05 12:54:14 +11:00
|
|
|
return $field->getValueFromData($this->data, $defaultValue);
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2014-06-29 13:35:47 +10:00
|
|
|
/**
|
|
|
|
* Returns a HTML encoded value containing the other fields this
|
|
|
|
* field depends on
|
2016-01-15 10:20:57 +01:00
|
|
|
* @param \Backend\Classes\FormField $field
|
2014-06-29 13:35:47 +10:00
|
|
|
* @return string
|
|
|
|
*/
|
2015-03-03 20:24:14 +11:00
|
|
|
protected function getFieldDepends($field)
|
2014-06-29 13:35:47 +10:00
|
|
|
{
|
2015-01-29 20:32:24 +11:00
|
|
|
if (!$field->dependsOn) {
|
2014-06-29 13:35:47 +10:00
|
|
|
return;
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-06-29 13:35:47 +10:00
|
|
|
|
2015-01-29 20:32:24 +11:00
|
|
|
$dependsOn = is_array($field->dependsOn) ? $field->dependsOn : [$field->dependsOn];
|
|
|
|
$dependsOn = htmlspecialchars(json_encode($dependsOn), ENT_QUOTES, 'UTF-8');
|
|
|
|
return $dependsOn;
|
2014-06-29 13:35:47 +10:00
|
|
|
}
|
|
|
|
|
2015-03-03 20:24:14 +11:00
|
|
|
/**
|
|
|
|
* Helper method to determine if field should be rendered
|
|
|
|
* with label and comments.
|
2016-01-15 10:20:57 +01:00
|
|
|
* @param \Backend\Classes\FormField $field
|
2015-03-03 20:24:14 +11:00
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
protected function showFieldLabels($field)
|
|
|
|
{
|
|
|
|
if (in_array($field->type, ['checkbox', 'switch', 'section'])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-13 13:18:48 +11:00
|
|
|
if ($field->type === 'widget') {
|
2015-08-07 19:06:04 +10:00
|
|
|
$widget = $this->makeFormFieldWidget($field);
|
2015-03-03 20:24:14 +11:00
|
|
|
return $widget->showLabels;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* Returns postback data from a submitted form.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return array
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
public function getSaveData()
|
|
|
|
{
|
2015-10-05 18:00:01 +11:00
|
|
|
$this->defineFormFields();
|
|
|
|
|
2015-09-26 11:41:02 +10:00
|
|
|
$result = [];
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-09-26 11:41:02 +10:00
|
|
|
/*
|
|
|
|
* Source data
|
|
|
|
*/
|
|
|
|
$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
|
|
|
|
|
|
|
/*
|
2015-09-26 11:41:02 +10:00
|
|
|
* Spin over each field and extract the postback value
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 13:37:06 +11:00
|
|
|
foreach ($this->allFields as $field) {
|
2014-05-14 23:24:20 +10:00
|
|
|
/*
|
|
|
|
* Handle HTML array, eg: item[key][another]
|
|
|
|
*/
|
2015-03-07 12:48:39 +11:00
|
|
|
$parts = HtmlHelper::nameToArray($field->fieldName);
|
2015-10-05 12:11:25 +11:00
|
|
|
if (($value = $this->dataArrayGet($data, $parts)) !== null) {
|
2015-09-26 11:41:02 +10:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Number fields should be converted to integers
|
|
|
|
*/
|
2016-02-13 13:18:48 +11:00
|
|
|
if ($field->type === 'number') {
|
2015-09-26 11:41:02 +10:00
|
|
|
$value = !strlen(trim($value)) ? null : (float) $value;
|
|
|
|
}
|
|
|
|
|
2015-10-05 12:11:25 +11:00
|
|
|
$this->dataArraySet($result, $parts, $value);
|
2014-09-13 18:29:10 +10:00
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Give widgets an opportunity to process the data.
|
|
|
|
*/
|
|
|
|
foreach ($this->formWidgets as $field => $widget) {
|
2015-03-07 12:48:39 +11:00
|
|
|
$parts = HtmlHelper::nameToArray($field);
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-10-05 12:11:25 +11:00
|
|
|
$widgetValue = $widget->getSaveValue($this->dataArrayGet($result, $parts));
|
|
|
|
$this->dataArraySet($result, $parts, $widgetValue);
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2015-09-26 11:41:02 +10:00
|
|
|
return $result;
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2015-02-17 20:58:38 +11:00
|
|
|
/*
|
|
|
|
* Allow the model to filter fields.
|
|
|
|
*/
|
|
|
|
protected function applyFiltersFromModel()
|
|
|
|
{
|
|
|
|
if (method_exists($this->model, 'filterFields')) {
|
2015-02-28 13:37:06 +11:00
|
|
|
$this->model->filterFields((object) $this->allFields, $this->getContext());
|
2015-02-17 20:58:38 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* Looks at the model for defined options.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param $field
|
|
|
|
* @param $fieldOptions
|
|
|
|
* @return mixed
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2014-08-01 18:18:09 +10:00
|
|
|
protected function getOptionsFromModel($field, $fieldOptions)
|
2014-05-14 23:24:20 +10:00
|
|
|
{
|
2014-06-16 18:00:41 +10:00
|
|
|
/*
|
|
|
|
* Advanced usage, supplied options are callable
|
|
|
|
*/
|
2014-06-01 10:15:33 +10:00
|
|
|
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:15:33 +10:00
|
|
|
}
|
2014-06-01 10:23:59 +10:00
|
|
|
|
2014-06-16 18:00:41 +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) {
|
2015-03-10 09:34:59 +11:00
|
|
|
list($model, $attribute) = $field->resolveModelAttribute($this->model, $field->fieldName);
|
2015-03-07 13:14:13 +11:00
|
|
|
|
|
|
|
$methodName = 'get'.studly_case($attribute).'Options';
|
2014-10-11 00:39:34 +02:00
|
|
|
if (
|
2015-03-07 13:14:13 +11:00
|
|
|
!$this->methodExists($model, $methodName) &&
|
|
|
|
!$this->methodExists($model, 'getDropdownOptions')
|
2014-10-11 00:39:34 +02:00
|
|
|
) {
|
|
|
|
throw new ApplicationException(Lang::get(
|
|
|
|
'backend::lang.field.options_method_not_exists',
|
2015-03-07 13:14:13 +11:00
|
|
|
['model'=>get_class($model), 'method'=>$methodName, 'field'=>$field->fieldName]
|
2014-10-11 00:39:34 +02:00
|
|
|
));
|
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-03-07 13:14:13 +11:00
|
|
|
if ($this->methodExists($model, $methodName)) {
|
|
|
|
$fieldOptions = $model->$methodName($field->value);
|
2014-11-04 17:41:48 +11:00
|
|
|
}
|
|
|
|
else {
|
2015-03-07 13:14:13 +11:00
|
|
|
$fieldOptions = $model->getDropdownOptions($attribute, $field->value);
|
2014-10-11 00:39:34 +02:00
|
|
|
}
|
2014-11-04 17:41:48 +11:00
|
|
|
}
|
2014-06-16 18:00:41 +10: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
|
|
|
|
2014-09-17 19:20:44 +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.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return \Illuminate\Routing\Route|mixed|string
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
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.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @return string
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
|
|
|
public function getContext()
|
|
|
|
{
|
2015-02-28 13:37:06 +11:00
|
|
|
return $this->context;
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2014-06-16 22:22:31 +10:00
|
|
|
/**
|
2016-01-15 21:57:47 +01:00
|
|
|
* Internal helper for method existence checks.
|
|
|
|
*
|
2014-06-16 22:22:31 +10:00
|
|
|
* @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);
|
|
|
|
}
|
2015-10-05 12:11:25 +11:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Variant to array_get() but preserves dots in key names.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param array $array
|
|
|
|
* @param array $parts
|
|
|
|
* @param null $default
|
|
|
|
* @return array|null
|
2015-10-05 12:11:25 +11:00
|
|
|
*/
|
|
|
|
protected function dataArrayGet(array $array, array $parts, $default = null)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
if ($parts === null) {
|
2015-10-05 12:11:25 +11:00
|
|
|
return $array;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count($parts) === 1) {
|
|
|
|
$key = array_shift($parts);
|
|
|
|
if (isset($array[$key])) {
|
|
|
|
return $array[$key];
|
2016-01-15 21:57:47 +01:00
|
|
|
} else {
|
2015-10-05 12:11:25 +11:00
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($parts as $segment) {
|
|
|
|
if (!is_array($array) || !array_key_exists($segment, $array)) {
|
|
|
|
return $default;
|
|
|
|
}
|
|
|
|
|
|
|
|
$array = $array[$segment];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $array;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Variant to array_set() but preserves dots in key names.
|
2016-01-15 21:57:47 +01:00
|
|
|
*
|
|
|
|
* @param array $array
|
|
|
|
* @param array $parts
|
|
|
|
* @param string $value
|
|
|
|
* @return array
|
2015-10-05 12:11:25 +11:00
|
|
|
*/
|
|
|
|
protected function dataArraySet(array &$array, array $parts, $value)
|
|
|
|
{
|
2016-01-15 21:57:47 +01:00
|
|
|
if ($parts === null) {
|
|
|
|
return $value;
|
2015-10-05 12:11:25 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
while (count($parts) > 1) {
|
|
|
|
$key = array_shift($parts);
|
|
|
|
|
|
|
|
if (!isset($array[$key]) || !is_array($array[$key])) {
|
|
|
|
$array[$key] = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
$array =& $array[$key];
|
|
|
|
}
|
|
|
|
|
|
|
|
$array[array_shift($parts)] = $value;
|
|
|
|
|
|
|
|
return $array;
|
|
|
|
}
|
2014-09-13 17:17:15 +10:00
|
|
|
}
|