2014-05-14 23:24:20 +10:00
|
|
|
<?php namespace Backend\FormWidgets;
|
|
|
|
|
2015-11-28 15:31:11 +11:00
|
|
|
use Db;
|
2014-05-14 23:24:20 +10:00
|
|
|
use Lang;
|
|
|
|
use Backend\Classes\FormWidgetBase;
|
2015-04-01 19:13:42 +01:00
|
|
|
use ApplicationException;
|
2015-01-28 18:03:35 +11:00
|
|
|
use SystemException;
|
2014-09-23 07:55:40 +10:00
|
|
|
use Illuminate\Database\Eloquent\Relations\Relation as RelationBase;
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Form Relationship
|
|
|
|
* Renders a field prepopulated with a belongsTo and belongsToHasMany relation.
|
|
|
|
*
|
|
|
|
* @package october\backend
|
|
|
|
* @author Alexey Bobkov, Samuel Georges
|
|
|
|
*/
|
|
|
|
class Relation extends FormWidgetBase
|
|
|
|
{
|
2016-03-25 18:01:58 +11:00
|
|
|
use \Backend\Traits\FormModelWidget;
|
|
|
|
|
2015-02-28 14:43:34 +11:00
|
|
|
//
|
|
|
|
// Configurable properties
|
|
|
|
//
|
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
2015-02-28 14:43:34 +11:00
|
|
|
* @var string Model column to use for the name reference
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 14:43:34 +11:00
|
|
|
public $nameFrom = 'name';
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 14:43:34 +11:00
|
|
|
* @var string Model column to use for the description reference
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 14:43:34 +11:00
|
|
|
public $descriptionFrom = 'description';
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2015-11-03 14:34:16 +01:00
|
|
|
/**
|
2015-11-28 15:31:11 +11:00
|
|
|
* @var string Custom SQL column selection to use for the name reference
|
2015-11-03 14:34:16 +01:00
|
|
|
*/
|
2015-11-28 15:31:11 +11:00
|
|
|
public $sqlSelect;
|
2015-11-03 14:34:16 +01:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
2015-02-28 14:43:34 +11:00
|
|
|
* @var string Empty value to use if the relation is singluar (belongsTo)
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 14:43:34 +11:00
|
|
|
public $emptyOption;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Object properties
|
|
|
|
//
|
2014-05-14 23:24:20 +10:00
|
|
|
|
|
|
|
/**
|
2015-02-28 14:43:34 +11:00
|
|
|
* {@inheritDoc}
|
2014-05-14 23:24:20 +10:00
|
|
|
*/
|
2015-02-28 14:43:34 +11:00
|
|
|
protected $defaultAlias = 'relation';
|
2014-05-14 23:24:20 +10:00
|
|
|
|
2014-05-28 12:37:38 +10:00
|
|
|
/**
|
2015-02-28 14:43:34 +11:00
|
|
|
* @var FormField Object used for rendering a simple field type
|
2014-05-28 12:37:38 +10:00
|
|
|
*/
|
2015-02-28 14:43:34 +11:00
|
|
|
public $renderFormField;
|
2014-05-28 12:37:38 +10:00
|
|
|
|
2014-05-14 23:24:20 +10:00
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
*/
|
|
|
|
public function init()
|
|
|
|
{
|
2015-02-28 14:43:34 +11:00
|
|
|
$this->fillFromConfig([
|
|
|
|
'nameFrom',
|
|
|
|
'descriptionFrom',
|
|
|
|
'emptyOption',
|
|
|
|
]);
|
2015-11-28 15:31:11 +11:00
|
|
|
|
|
|
|
if (isset($this->config->select)) {
|
|
|
|
$this->sqlSelect = $this->config->select;
|
|
|
|
}
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* {@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()
|
|
|
|
{
|
2014-10-10 23:50:05 +02:00
|
|
|
return $this->renderFormField = RelationBase::noConstraints(function () {
|
2014-09-23 07:55:40 +10:00
|
|
|
|
|
|
|
$field = clone $this->formField;
|
2015-03-23 20:02:59 +11:00
|
|
|
$relationObject = $this->getRelationObject();
|
|
|
|
$query = $relationObject->newQuery();
|
2014-09-23 07:55:40 +10:00
|
|
|
|
2015-03-23 20:02:59 +11:00
|
|
|
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
|
|
$relationType = $model->getRelationType($attribute);
|
|
|
|
$relationModel = $model->makeRelation($attribute);
|
2014-09-23 07:55:40 +10:00
|
|
|
|
2015-03-23 20:02:59 +11:00
|
|
|
if (in_array($relationType, ['belongsToMany', 'morphToMany', 'morphedByMany', 'hasMany'])) {
|
2014-09-23 07:55:40 +10:00
|
|
|
$field->type = 'checkboxlist';
|
2014-11-04 12:34:45 +11:00
|
|
|
}
|
2015-03-23 20:02:59 +11:00
|
|
|
elseif (in_array($relationType, ['belongsTo', 'hasOne'])) {
|
2014-09-23 07:55:40 +10:00
|
|
|
$field->type = 'dropdown';
|
|
|
|
}
|
|
|
|
|
2015-01-21 17:01:07 +11:00
|
|
|
$field->placeholder = $this->emptyOption;
|
|
|
|
|
2014-10-10 23:50:05 +02:00
|
|
|
// It is safe to assume that if the model and related model are of
|
2014-09-23 07:55:40 +10:00
|
|
|
// the exact same class, then it cannot be related to itself
|
2015-03-23 20:02:59 +11:00
|
|
|
if ($model->exists && (get_class($model) == get_class($relationModel))) {
|
|
|
|
$query->where($relationModel->getKeyName(), '<>', $model->getKey());
|
2014-09-23 07:55:40 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 = [];
|
|
|
|
|
2015-11-28 15:31:11 +11:00
|
|
|
// 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) {
|
2015-11-03 14:34:16 +01:00
|
|
|
$nameFrom = 'selection';
|
2015-11-28 15:31:11 +11:00
|
|
|
$selectColumn = $usesTree ? '*' : $relationModel->getKeyName();
|
|
|
|
$result = $query->select($selectColumn, Db::raw($this->sqlSelect . ' AS ' . $nameFrom));
|
2015-11-03 14:34:16 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
$nameFrom = $this->nameFrom;
|
2015-11-28 15:31:11 +11:00
|
|
|
$result = $query->getQuery()->get();
|
2015-11-03 14:34:16 +01:00
|
|
|
}
|
|
|
|
|
2015-11-28 15:31:11 +11:00
|
|
|
$field->options = $usesTree
|
|
|
|
? $result->listsNested($nameFrom, $relationModel->getKeyName())
|
|
|
|
: $result->lists($nameFrom, $relationModel->getKeyName());
|
2014-09-23 07:55:40 +10:00
|
|
|
|
|
|
|
return $field;
|
|
|
|
});
|
2014-05-14 23:24:20 +10:00
|
|
|
}
|
|
|
|
|
2014-05-28 13:00:31 +10:00
|
|
|
/**
|
|
|
|
* {@inheritDoc}
|
|
|
|
*/
|
2015-01-05 09:43:39 +11:00
|
|
|
public function getSaveValue($value)
|
2014-05-28 13:00:31 +10:00
|
|
|
{
|
2014-10-10 23:50:05 +02:00
|
|
|
if (is_string($value) && !strlen($value)) {
|
2014-05-29 19:35:46 +10:00
|
|
|
return null;
|
2014-10-10 23:50:05 +02:00
|
|
|
}
|
2014-05-29 19:35:46 +10:00
|
|
|
|
2014-10-10 23:50:05 +02:00
|
|
|
if (is_array($value) && !count($value)) {
|
2014-05-29 19:35:46 +10:00
|
|
|
return null;
|
2014-10-10 23:50:05 +02:00
|
|
|
}
|
2014-05-29 19:35:46 +10:00
|
|
|
|
|
|
|
return $value;
|
2014-05-28 13:00:31 +10:00
|
|
|
}
|
2014-10-10 23:50:05 +02:00
|
|
|
}
|