Samuel Georges cb86e655dd Fixes disabled relation nulling value
Just like DatePicker, relation and even regular fields should omitted from the data set
The same logic should apply to hidden fields
Fixes #1827
Recompile assets
2016-05-15 06:47:28 +10:00

172 lines
4.8 KiB
PHP

<?php namespace Backend\FormWidgets;
use Db;
use Lang;
use Backend\Classes\FormField;
use Backend\Classes\FormWidgetBase;
use ApplicationException;
use SystemException;
use Illuminate\Database\Eloquent\Relations\Relation as RelationBase;
/**
* Form Relationship
* Renders a field prepopulated with a belongsTo and belongsToHasMany relation.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class Relation extends FormWidgetBase
{
use \Backend\Traits\FormModelWidget;
//
// Configurable properties
//
/**
* @var string Model column to use for the name reference
*/
public $nameFrom = 'name';
/**
* @var string Model column to use for the description reference
*/
public $descriptionFrom = 'description';
/**
* @var string Custom SQL column selection to use for the name reference
*/
public $sqlSelect;
/**
* @var string Empty value to use if the relation is singluar (belongsTo)
*/
public $emptyOption;
//
// Object properties
//
/**
* {@inheritDoc}
*/
protected $defaultAlias = 'relation';
/**
* @var FormField Object used for rendering a simple field type
*/
public $renderFormField;
/**
* {@inheritDoc}
*/
public function init()
{
$this->fillFromConfig([
'nameFrom',
'descriptionFrom',
'emptyOption',
]);
if (isset($this->config->select)) {
$this->sqlSelect = $this->config->select;
}
}
/**
* {@inheritDoc}
*/
public function render()
{
$this->prepareVars();
return $this->makePartial('relation');
}
/**
* Prepares the view data
*/
public function prepareVars()
{
$this->vars['field'] = $this->makeRenderFormField();
}
/**
* Makes the form object used for rendering a simple field type
*/
protected function makeRenderFormField()
{
return $this->renderFormField = RelationBase::noConstraints(function () {
$field = clone $this->formField;
$relationObject = $this->getRelationObject();
$query = $relationObject->newQuery();
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
$relationType = $model->getRelationType($attribute);
$relationModel = $model->makeRelation($attribute);
if (in_array($relationType, ['belongsToMany', 'morphToMany', 'morphedByMany', 'hasMany'])) {
$field->type = 'checkboxlist';
}
elseif (in_array($relationType, ['belongsTo', 'hasOne'])) {
$field->type = 'dropdown';
}
$field->placeholder = $this->emptyOption;
// It is safe to assume that if the model and related model are of
// the exact same class, then it cannot be related to itself
if ($model->exists && (get_class($model) == get_class($relationModel))) {
$query->where($relationModel->getKeyName(), '<>', $model->getKey());
}
// Even though "no constraints" is applied, belongsToMany constrains the query
// by joining its pivot table. Remove all joins from the query.
$query->getQuery()->getQuery()->joins = [];
// Determine if the model uses a tree trait
$treeTraits = ['October\Rain\Database\Traits\NestedTree', 'October\Rain\Database\Traits\SimpleTree'];
$usesTree = count(array_intersect($treeTraits, class_uses($relationModel))) > 0;
// The "sqlSelect" config takes precedence over "nameFrom".
// A virtual column called "selection" will contain the result.
// Tree models must select all columns to return parent columns, etc.
if ($this->sqlSelect) {
$nameFrom = 'selection';
$selectColumn = $usesTree ? '*' : $relationModel->getKeyName();
$result = $query->select($selectColumn, Db::raw($this->sqlSelect . ' AS ' . $nameFrom));
}
else {
$nameFrom = $this->nameFrom;
$result = $query->getQuery()->get();
}
$field->options = $usesTree
? $result->listsNested($nameFrom, $relationModel->getKeyName())
: $result->lists($nameFrom, $relationModel->getKeyName());
return $field;
});
}
/**
* {@inheritDoc}
*/
public function getSaveValue($value)
{
if ($this->formField->disabled || $this->formField->hidden) {
return FormField::NO_SAVE_DATA;
}
if (is_string($value) && !strlen($value)) {
return null;
}
if (is_array($value) && !count($value)) {
return null;
}
return $value;
}
}