winter/modules/backend/behaviors/RelationController.php

1124 lines
33 KiB
PHP
Raw Normal View History

2014-05-14 23:24:20 +10:00
<?php namespace Backend\Behaviors;
use DB;
use Lang;
use Event;
use Form as FormHelper;
2014-05-14 23:24:20 +10:00
use Backend\Classes\ControllerBehavior;
use System\Classes\ApplicationException;
use October\Rain\Database\Model;
/**
* Relation Controller Behavior
* Uses a combination of lists and forms for managing Model relations.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*/
class RelationController extends ControllerBehavior
{
/**
* @var const Postback parameter for the active relationship field.
*/
const PARAM_FIELD = '_relation_field';
/**
* @var const Postback parameter for the active management mode.
*/
const PARAM_MODE = '_relation_mode';
/**
* @var Backend\Classes\WidgetBase Reference to the search widget object.
*/
protected $searchWidget;
2014-05-14 23:24:20 +10:00
/**
* @var Backend\Classes\WidgetBase Reference to the toolbar widget object.
*/
2014-08-01 18:20:55 +10:00
protected $toolbarWidget;
2014-05-14 23:24:20 +10:00
/**
* @var Backend\Classes\WidgetBase Reference to the widget used for viewing (list or form).
*/
2014-08-01 18:20:55 +10:00
protected $viewWidget;
2014-05-14 23:24:20 +10:00
/**
* @var Backend\Classes\WidgetBase Reference to the widget used for relation management.
*/
2014-08-01 18:20:55 +10:00
protected $manageWidget;
2014-05-14 23:24:20 +10:00
/**
* @var Backend\Classes\WidgetBase Reference to widget for relations with pivot data.
*/
2014-08-01 18:20:55 +10:00
protected $pivotWidget;
2014-05-14 23:24:20 +10:00
/**
* {@inheritDoc}
*/
protected $requiredProperties = ['relationConfig'];
/**
* @var array Properties that must exist for each relationship definition.
*/
protected $requiredRelationProperties = ['label'];
2014-05-14 23:24:20 +10:00
/**
* @var array Configuration values that must exist when applying the primary config file.
*/
protected $requiredConfig = [];
/**
* @var array Original configuration values
*/
2014-08-01 18:20:55 +10:00
protected $originalConfig;
/**
* @var bool Has the behavior been initialized.
*/
2014-08-01 18:20:55 +10:00
protected $initialized = false;
2014-05-14 23:24:20 +10:00
/**
* @var string Relationship type
*/
public $relationType;
/**
* @var string Relationship name
*/
public $relationName;
/**
* @var Model Relationship model
*/
public $relationModel;
/**
* @var Model Relationship object
*/
public $relationObject;
/**
* @var Model The parent model of the relationship.
*/
protected $model;
/**
* @var Model The relationship field as defined in the configuration.
*/
protected $field;
/**
* @var string A unique alias to pass to widgets.
*/
protected $alias;
/**
* @var array The set of buttons to display in view mode.
*/
protected $toolbarButtons;
/**
* @var Model Reference to the model used for viewing (form only).
*/
protected $viewModel;
2014-05-14 23:24:20 +10:00
/**
* @var string Relation has many (multi) or has one (single).
*/
protected $viewMode;
/**
* @var string Management of relation as list, form, or pivot.
*/
protected $manageMode;
/**
2014-05-17 18:08:01 +02:00
* @var int Primary id of an existing relation record.
2014-05-14 23:24:20 +10:00
*/
protected $manageId;
/**
* @var string Active session key, used for deferred bindings.
*/
public $sessionKey;
/**
* @var bool Disables the ability to add, update, delete or create relations.
*/
public $readOnly = false;
2014-05-14 23:24:20 +10:00
/**
* Behavior constructor
* @param Backend\Classes\Controller $controller
* @return void
*/
public function __construct($controller)
{
parent::__construct($controller);
2014-05-24 16:57:38 +10:00
$this->addJs('js/october.relation.js', 'core');
$this->addCss('css/relation.css', 'core');
2014-05-14 23:24:20 +10:00
/*
* Build configuration
*/
$this->config = $this->originalConfig = $this->makeConfig($controller->relationConfig, $this->requiredConfig);
2014-05-14 23:24:20 +10:00
}
/**
* Prepare the widgets used by this behavior
* @param Model $model
* @param string $field
* @return void
*/
public function initRelation($model, $field = null)
{
2014-10-10 22:34:57 +02:00
if ($field == null) {
$field = post(self::PARAM_FIELD);
2014-10-10 22:34:57 +02:00
}
$this->config = $this->originalConfig;
2014-05-14 23:24:20 +10:00
$this->model = $model;
$this->field = $field;
2014-10-10 22:34:57 +02:00
if ($field == null) {
2014-05-14 23:24:20 +10:00
return;
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if (!$this->model) {
throw new ApplicationException(Lang::get(
'backend::lang.relation.missing_model',
['class'=>get_class($this->controller)]
));
}
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if (!$this->model instanceof Model) {
throw new ApplicationException(Lang::get(
'backend::lang.model.invalid_class',
['model'=>get_class($this->model), 'class'=>get_class($this->controller)]
));
}
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if (!$this->getConfig($field)) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(Lang::get('backend::lang.relation.missing_definition', compact('field')));
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
$this->alias = camel_case('relation ' . $field);
$this->config = $this->makeConfig($this->getConfig($field), $this->requiredRelationProperties);
2014-05-14 23:24:20 +10:00
/*
* Relationship details
*/
$this->relationName = $field;
$this->relationType = $this->model->getRelationType($field);
$this->relationObject = $this->model->{$field}();
$this->relationModel = $this->relationObject->getRelated();
$this->readOnly = $this->getConfig('readOnly');
$this->toolbarButtons = $this->evalToolbarButtons();
$this->viewMode = $this->viewMode ?: $this->evalViewMode();
$this->manageMode = $this->manageMode ?: $this->evalManageMode();
2014-05-14 23:24:20 +10:00
$this->manageId = post('manage_id');
/*
* Toolbar widget
*/
2014-10-10 22:34:57 +02:00
if ($this->toolbarWidget = $this->makeToolbarWidget()) {
$this->toolbarWidget->bindToController();
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* View widget
*/
2014-10-10 22:34:57 +02:00
if ($this->viewWidget = $this->makeViewWidget()) {
$this->viewWidget->bindToController();
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Manage widget
*/
2014-10-10 22:34:57 +02:00
if ($this->manageWidget = $this->makeManageWidget()) {
$this->manageWidget->bindToController();
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Pivot widget
*/
if ($this->manageMode == 'pivot') {
2014-10-10 22:34:57 +02:00
if ($this->pivotWidget = $this->makePivotWidget()) {
$this->pivotWidget->bindToController();
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
}
}
/**
* Determine the default buttons based on the model relationship type.
* @return string
*/
protected function evalToolbarButtons()
{
if ($buttons = $this->getConfig('view[toolbarButtons]')) {
return is_array($buttons)
? $buttons
: array_map('trim', explode('|', $buttons));
}
switch ($this->relationType) {
case 'hasMany':
case 'belongsToMany':
2015-01-25 13:10:17 +11:00
return ['add', 'create', 'delete', 'remove'];
case 'hasOne':
2015-01-25 13:10:17 +11:00
case 'belongsTo':
return ['create', 'update', 'link', 'delete', 'unlink'];
}
}
2014-05-14 23:24:20 +10:00
/**
* Determine the view mode based on the model relationship type.
* @return string
*/
protected function evalViewMode()
{
switch ($this->relationType) {
case 'hasMany':
case 'belongsToMany':
return 'multi';
case 'hasOne':
case 'belongsTo':
return 'single';
}
}
/**
* Determine the management mode based on the relation type and settings.
* @return string
*/
protected function evalManageMode()
{
if ($mode = post(self::PARAM_MODE)) {
return $mode;
}
2014-05-14 23:24:20 +10:00
switch ($this->relationType) {
case 'belongsTo':
$mode = 'list';
break;
2014-05-14 23:24:20 +10:00
case 'belongsToMany':
$mode = (isset($this->config->pivot)) ? 'pivot' : 'list';
break;
case 'hasOne':
case 'hasMany':
$mode = 'form';
break;
}
return $mode;
}
/**
* Renders the relationship manager.
* @param string $field The relationship field.
* @param array $options
* @return string Rendered HTML for the relationship manager.
*/
public function relationRender($field, $options = [])
{
$field = $this->validateField($field);
2014-10-10 22:34:57 +02:00
if (is_string($options)) {
$options = ['sessionKey' => $options];
}
2014-05-14 23:24:20 +10:00
$this->prepareVars();
/*
* Session key
*/
2014-10-10 22:34:57 +02:00
if (isset($options['sessionKey'])) {
$this->sessionKey = $options['sessionKey'];
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* Determine the partial to use based on the supplied section option
*/
$section = (isset($options['section'])) ? $options['section'] : null;
switch (strtolower($section)) {
case 'toolbar':
return $this->toolbarWidget ? $this->toolbarWidget->render() : null;
2014-05-14 23:24:20 +10:00
case 'view':
2014-06-20 21:36:44 +10:00
return $this->relationMakePartial('view');
2014-05-14 23:24:20 +10:00
default:
2014-06-20 21:36:44 +10:00
return $this->relationMakePartial('container');
2014-05-14 23:24:20 +10:00
}
}
/**
* Refreshes the relation container only, useful for returning in custom AJAX requests.
* @param string $field Relation definition.
* @return array The relation element selector as the key, and the relation view contents are the value.
*/
public function relationRefresh($field = null)
{
$field = $this->validateField($field);
$result = ['#'.$this->relationGetId('view') => $this->relationRenderView()];
if ($toolbar = $this->relationRenderToolbar()) {
$result['#'.$this->relationGetId('toolbar')] = $toolbar;
}
return $result;
}
2014-05-14 23:24:20 +10:00
/**
* Renders the toolbar only.
* @param string $field The relationship field.
* @return string Rendered HTML for the toolbar.
*/
public function relationRenderToolbar($field = null)
{
return $this->relationRender($field, ['section' => 'toolbar']);
}
/**
* Renders the view only.
* @param string $field The relationship field.
* @return string Rendered HTML for the view.
*/
public function relationRenderView($field = null)
{
return $this->relationRender($field, ['section' => 'view']);
}
/**
* Validates the supplied field and initializes the relation manager.
* @param string $field The relationship field.
* @return string The active field name.
*/
2014-08-01 18:18:09 +10:00
protected function validateField($field = null)
2014-05-14 23:24:20 +10:00
{
$field = $field ?: post(self::PARAM_FIELD);
2014-10-10 22:34:57 +02:00
if ($field && $field != $this->field) {
2014-05-14 23:24:20 +10:00
$this->initRelation($this->model, $field);
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if (!$field && !$this->field) {
2014-05-14 23:24:20 +10:00
throw new ApplicationException(Lang::get('backend::lang.relation.missing_definition', compact('field')));
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
return $field ?: $this->field;
}
/**
* Prepares the view data.
* @return void
*/
public function prepareVars()
{
$this->vars['relationManageId'] = $this->manageId;
$this->vars['relationLabel'] = $this->config->label ?: $this->field;
$this->vars['relationField'] = $this->field;
$this->vars['relationType'] = $this->relationType;
$this->vars['relationSearchWidget'] = $this->searchWidget;
2014-05-14 23:24:20 +10:00
$this->vars['relationToolbarWidget'] = $this->toolbarWidget;
$this->vars['relationManageMode'] = $this->manageMode;
$this->vars['relationManageWidget'] = $this->manageWidget;
$this->vars['relationToolbarButtons'] = $this->toolbarButtons;
$this->vars['relationViewMode'] = $this->viewMode;
$this->vars['relationViewWidget'] = $this->viewWidget;
$this->vars['relationViewModel'] = $this->viewModel;
2014-05-14 23:24:20 +10:00
$this->vars['relationPivotWidget'] = $this->pivotWidget;
$this->vars['relationSessionKey'] = $this->relationGetSessionKey();
2014-05-14 23:24:20 +10:00
}
/**
* The controller action is responsible for supplying the parent model
* so it's action must be fired. Additionally, each AJAX request must
* supply the relation's field name (_relation_field).
*/
protected function beforeAjax()
{
2014-10-10 22:34:57 +02:00
if ($this->initialized) {
return;
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
$this->controller->pageAction();
$this->validateField();
2014-05-14 23:24:20 +10:00
$this->prepareVars();
$this->initialized = true;
2014-05-14 23:24:20 +10:00
}
/**
* Controller accessor for making partials within this behavior.
* @param string $partial
* @param array $params
* @return string Partial contents
*/
public function relationMakePartial($partial, $params = [])
{
2014-07-11 22:24:43 +10:00
$contents = $this->controller->makePartial('relation_'.$partial, $params + $this->vars, false);
2014-10-10 22:34:57 +02:00
if (!$contents) {
2014-06-20 21:36:44 +10:00
$contents = $this->makePartial($partial, $params);
2014-10-10 22:34:57 +02:00
}
2014-06-20 21:36:44 +10:00
return $contents;
2014-05-14 23:24:20 +10:00
}
/**
* Returns a unique ID for this relation and field combination.
* @param string $suffix A suffix to use with the identifier.
* @return string
*/
public function relationGetId($suffix = null)
{
2014-09-29 13:12:34 +10:00
$id = class_basename($this);
2014-10-10 22:34:57 +02:00
if ($this->field) {
2014-05-14 23:24:20 +10:00
$id .= '-' . $this->field;
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if ($suffix !== null) {
2014-05-14 23:24:20 +10:00
$id .= '-' . $suffix;
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
return $this->controller->getId($id);
}
/**
2014-05-17 18:08:01 +02:00
* Returns the existing record IDs for the relation.
2014-05-14 23:24:20 +10:00
*/
2014-08-01 18:18:09 +10:00
protected function findExistingRelationIds($checkIds = null)
2014-05-14 23:24:20 +10:00
{
$foreignKeyName = $this->relationModel->getQualifiedKeyName();
2014-05-14 23:24:20 +10:00
$results = $this->relationObject
->getBaseQuery()
->select($foreignKeyName);
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if ($checkIds !== null && is_array($checkIds) && count($checkIds)) {
$results = $results->whereIn($foreignKeyName, $checkIds);
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
return $results->lists($foreignKeyName);
2014-05-14 23:24:20 +10:00
}
//
// Overrides
//
/**
* Controller override: Extend the query used for populating the list
* after the default query is processed.
* @param October\Rain\Database\Builder $query
* @param string $field
*/
public function relationExtendQuery($query, $field)
{
}
2014-05-14 23:24:20 +10:00
//
// AJAX (Buttons)
//
public function onRelationButtonAdd()
{
$this->manageMode = 'list';
return $this->onRelationManageForm();
}
public function onRelationButtonCreate()
{
$this->manageMode = 'form';
return $this->onRelationManageForm();
}
public function onRelationButtonDelete()
{
return $this->onRelationManageDelete();
}
public function onRelationButtonLink()
{
$this->manageMode = 'list';
return $this->onRelationManageForm();
}
public function onRelationButtonUnlink()
{
return $this->onRelationManageRemove();
}
public function onRelationButtonRemove()
{
return $this->onRelationManageRemove();
}
public function onRelationButtonUpdate()
{
$this->manageMode = 'form';
return $this->onRelationManageForm();
}
2014-05-14 23:24:20 +10:00
//
// AJAX
//
public function onRelationManageForm()
{
$this->beforeAjax();
2014-10-10 22:34:57 +02:00
if ($this->manageMode == 'pivot' && $this->manageId) {
2014-05-14 23:24:20 +10:00
return $this->onRelationManagePivotForm();
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
// The form should not share its session key with the parent
$this->vars['newSessionKey'] = str_random(40);
2014-05-14 23:24:20 +10:00
$view = 'manage_' . $this->manageMode;
2014-06-20 21:36:44 +10:00
return $this->relationMakePartial($view);
2014-05-14 23:24:20 +10:00
}
/**
* Create a new related model
*/
public function onRelationManageCreate()
2014-05-14 23:24:20 +10:00
{
$this->manageMode = 'form';
2014-05-14 23:24:20 +10:00
$this->beforeAjax();
$saveData = $this->manageWidget->getSaveData();
2014-05-14 23:24:20 +10:00
if ($this->viewMode == 'multi') {
if ($this->relationType == 'hasMany') {
$newModel = $this->relationObject->create($saveData, $this->relationGetSessionKey(true));
}
elseif ($this->relationType == 'belongsToMany') {
$newModel = $this->relationObject->create($saveData, [], $this->relationGetSessionKey(true));
}
$newModel->commitDeferred($this->manageWidget->getSessionKey());
}
elseif ($this->viewMode == 'single') {
$newModel = $this->viewModel;
$this->viewWidget->setFormValues($saveData);
if ($this->relationType == 'belongsTo') {
$newModel->save();
$this->relationObject->associate($newModel);
$this->relationObject->getParent()->save();
}
elseif ($this->relationType == 'hasOne') {
$this->relationObject->add($newModel);
}
}
return $this->relationRefresh();
2014-05-14 23:24:20 +10:00
}
/**
* Updated an existing related model's fields
*/
public function onRelationManageUpdate()
2014-05-14 23:24:20 +10:00
{
$this->manageMode = 'form';
2014-05-14 23:24:20 +10:00
$this->beforeAjax();
$saveData = $this->manageWidget->getSaveData();
if ($this->viewMode == 'multi') {
$model = $this->relationObject->find($this->manageId);
$model->save($saveData, $this->manageWidget->getSessionKey());
}
elseif ($this->viewMode == 'single') {
$this->viewWidget->setFormValues($saveData);
$this->viewModel->save();
}
2014-05-14 23:24:20 +10:00
return ['#'.$this->relationGetId('view') => $this->relationRenderView()];
}
/**
* Delete an existing related model completely
*/
2014-05-14 23:24:20 +10:00
public function onRelationManageDelete()
{
$this->beforeAjax();
/*
* Multiple (has many, belongs to many)
*/
if ($this->viewMode == 'multi') {
if (($checkedIds = post('checked')) && is_array($checkedIds)) {
$relatedModel = $this->relationObject->getRelated();
foreach ($checkedIds as $relationId) {
if (!$obj = $relatedModel->find($relationId)) {
continue;
}
$obj->delete();
2014-10-10 22:34:57 +02:00
}
}
}
/*
* Single (belongs to, has one)
*/
elseif ($this->viewMode == 'single') {
$relatedModel = $this->viewModel;
if ($relatedModel->exists) {
$relatedModel->delete();
}
$this->viewWidget->setFormValues([]);
$this->viewModel = $this->relationModel;
}
return $this->relationRefresh();
2014-05-14 23:24:20 +10:00
}
/**
* Add an existing related model to the primary model
*/
public function onRelationManageAdd()
2014-05-14 23:24:20 +10:00
{
$this->beforeAjax();
$recordId = post('record_id');
/*
* Add
*/
if ($this->viewMode == 'multi') {
$checkedIds = $recordId ? [$recordId] : post('checked');
if (is_array($checkedIds)) {
/*
* Remove existing relations from the array
*/
$existingIds = $this->findExistingRelationIds($checkedIds);
$checkedIds = array_diff($checkedIds, $existingIds);
$foreignKeyName = $this->relationModel->getKeyName();
$models = $this->relationModel->whereIn($foreignKeyName, $checkedIds)->get();
foreach ($models as $model) {
if ($this->model->exists) {
$this->relationObject->add($model);
}
else {
$this->relationObject->add($model, $this->relationGetSessionKey());
}
2014-10-10 22:34:57 +02:00
}
}
}
/*
* Link
*/
elseif ($this->viewMode == 'single') {
if ($recordId && ($model = $this->relationModel->find($recordId))) {
if ($this->relationType == 'belongsTo') {
$this->relationObject->associate($model);
$this->relationObject->getParent()->save();
}
elseif ($this->relationType == 'hasOne') {
$this->relationObject->add($model);
}
$this->viewWidget->setFormValues($model->attributes);
}
}
2014-05-14 23:24:20 +10:00
return $this->relationRefresh();
2014-05-14 23:24:20 +10:00
}
/**
* Remove an existing related model from the primary model
*/
public function onRelationManageRemove()
{
$this->beforeAjax();
$recordId = post('record_id');
/*
* Remove
*/
if ($this->viewMode == 'multi') {
$checkedIds = $recordId ? [$recordId] : post('checked');
if (is_array($checkedIds)) {
if ($this->relationType == 'belongsToMany') {
$this->relationObject->detach($checkedIds);
}
elseif ($this->relationType == 'hasMany') {
$relatedModel = $this->relationObject->getRelated();
foreach ($checkedIds as $relationId) {
if ($obj = $relatedModel->find($relationId)) {
$this->relationObject->remove($obj);
}
}
}
}
}
/*
* Unlink
*/
elseif ($this->viewMode == 'single') {
if ($this->relationType == 'belongsTo') {
$this->relationObject->dissociate();
$this->relationObject->getParent()->save();
}
elseif ($this->relationType == 'hasOne') {
if ($obj = $this->relationModel->find($recordId)) {
$this->relationObject->remove($obj);
}
elseif ($this->viewModel->exists) {
$this->relationObject->remove($this->viewModel);
}
}
$this->viewWidget->setFormValues([]);
}
return $this->relationRefresh();
}
2014-05-14 23:24:20 +10:00
public function onRelationManagePivotForm()
{
$this->beforeAjax();
$this->vars['foreignId'] = post('foreign_id');
2014-06-20 21:36:44 +10:00
return $this->relationMakePartial('pivot_form');
2014-05-14 23:24:20 +10:00
}
public function onRelationManagePivotCreate()
{
$this->beforeAjax();
$foreignId = post('foreign_id');
$foreignModel = $this->relationModel->find($foreignId);
$saveData = $this->pivotWidget->getSaveData();
/*
2014-05-17 18:08:01 +02:00
* Check for existing relation
2014-05-14 23:24:20 +10:00
*/
$foreignKeyName = $this->relationModel->getQualifiedKeyName();
$existing = $this->relationObject->where($foreignKeyName, $foreignId)->count();
2014-05-14 23:24:20 +10:00
2014-10-10 22:34:57 +02:00
if (!$existing) {
2014-05-14 23:24:20 +10:00
$this->relationObject->add($foreignModel, null, $saveData);
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
return ['#'.$this->relationGetId('view') => $this->relationRenderView()];
}
public function onRelationManagePivotUpdate()
{
$this->beforeAjax();
$saveData = $this->pivotWidget->getSaveData();
$this->relationObject->updateExistingPivot($this->manageId, $saveData, true);
return ['#'.$this->relationGetId('view') => $this->relationRenderView()];
}
//
// Widgets
//
protected function makeSearchWidget()
{
$config = $this->makeConfig();
$config->alias = $this->alias . 'ManageSearch';
$config->growable = false;
$config->prompt = 'backend::lang.list.search_prompt';
$widget = $this->makeWidget('Backend\Widgets\Search', $config);
$widget->cssClasses[] = 'recordfinder-search';
return $widget;
}
2014-05-14 23:24:20 +10:00
protected function makeToolbarWidget()
{
$defaultConfig = [];
/*
* Add buttons to toolbar
*/
$defaultButtons = null;
if (!$this->readOnly) {
$defaultButtons = '~/modules/backend/behaviors/relationcontroller/partials/_toolbar.htm';
2014-10-10 22:34:57 +02:00
}
$defaultConfig['buttons'] = $this->getConfig('view[toolbarPartial]', $defaultButtons);
/*
* Make config
*/
2014-05-14 23:24:20 +10:00
$toolbarConfig = $this->makeConfig($this->getConfig('toolbar', $defaultConfig));
$toolbarConfig->alias = $this->alias . 'Toolbar';
2014-09-06 12:51:39 +10:00
/*
* Add search to toolbar
*/
$useSearch = $this->viewMode == 'multi' && $this->getConfig('view[showSearch]');
if ($useSearch) {
2014-09-06 12:51:39 +10:00
$toolbarConfig->search = [
'prompt' => 'backend::lang.list.search_prompt'
2014-09-06 12:51:39 +10:00
];
}
/*
* No buttons, no search should mean no toolbar
*/
if (empty($toolbarConfig->search) && empty($toolbarConfig->buttons))
return;
$toolbarWidget = $this->makeWidget('Backend\Widgets\Toolbar', $toolbarConfig);
$toolbarWidget->cssClasses[] = 'list-header';
2014-09-06 12:51:39 +10:00
return $toolbarWidget;
2014-05-14 23:24:20 +10:00
}
protected function makeViewWidget()
{
/*
* Multiple (has many, belongs to many)
*/
if ($this->viewMode == 'multi') {
$config = $this->makeConfig($this->config->list);
$config->model = $this->relationModel;
$config->alias = $this->alias . 'ViewList';
$config->showSorting = $this->getConfig('view[showSorting]', true);
$config->defaultSort = $this->getConfig('view[defaultSort]');
$config->recordsPerPage = $this->getConfig('view[recordsPerPage]');
$config->showCheckboxes = $this->getConfig('view[showCheckboxes]', !$this->readOnly);
$defaultOnClick = sprintf(
"$.oc.relationBehavior.clickViewListRecord(:id, '%s', '%s')",
$this->field,
$this->relationGetSessionKey()
);
2014-05-14 23:24:20 +10:00
$config->recordOnClick = $this->getConfig('view[recordOnClick]', $defaultOnClick);
$config->recordUrl = $this->getConfig('view[recordUrl]', null);
2014-10-10 22:34:57 +02:00
if ($emptyMessage = $this->getConfig('emptyMessage')) {
2014-06-24 18:53:05 +10:00
$config->noRecordsMessage = $emptyMessage;
2014-10-10 22:34:57 +02:00
}
2014-06-24 18:53:05 +10:00
2014-09-06 12:51:39 +10:00
/*
* Constrain the query by the relationship and deferred items
*/
2014-05-14 23:24:20 +10:00
$widget = $this->makeWidget('Backend\Widgets\Lists', $config);
2014-10-10 22:34:57 +02:00
$widget->bindEvent('list.extendQuery', function ($query) {
$this->controller->relationExtendQuery($query, $this->field);
2014-05-14 23:24:20 +10:00
$this->relationObject->setQuery($query);
if ($sessionKey = $this->relationGetSessionKey()) {
$this->relationObject->withDeferred($sessionKey);
}
elseif ($this->model->exists) {
$this->relationObject->addConstraints();
}
2014-05-14 23:24:20 +10:00
});
2014-09-06 12:51:39 +10:00
/*
* Constrain the list by the search widget, if available
*/
if ($this->toolbarWidget && $this->getConfig('view[showSearch]')) {
if ($searchWidget = $this->toolbarWidget->getSearchWidget()) {
2014-10-10 22:34:57 +02:00
$searchWidget->bindEvent('search.submit', function () use ($widget, $searchWidget) {
2014-09-06 12:51:39 +10:00
$widget->setSearchTerm($searchWidget->getActiveTerm());
return $widget->onRefresh();
});
$searchWidget->setActiveTerm(null);
2014-09-06 12:51:39 +10:00
}
}
2014-11-04 17:41:48 +11:00
}
2014-05-14 23:24:20 +10:00
/*
* Single (belongs to, has one)
*/
2014-11-04 17:41:48 +11:00
elseif ($this->viewMode == 'single') {
$query = $this->relationObject;
$this->controller->relationExtendQuery($query, $this->field);
$this->viewModel = $query->getResults() ?: $this->relationModel;
2014-05-14 23:24:20 +10:00
$config = $this->makeConfig($this->config->form);
$config->model = $this->viewModel;
2014-09-29 13:12:34 +10:00
$config->arrayName = class_basename($this->relationModel);
2014-05-14 23:24:20 +10:00
$config->context = 'relation';
$config->alias = $this->alias . 'ViewForm';
$widget = $this->makeWidget('Backend\Widgets\Form', $config);
$widget->previewMode = true;
2014-05-14 23:24:20 +10:00
}
return $widget;
}
protected function makeManageWidget()
{
$widget = null;
2014-05-14 23:24:20 +10:00
/*
* Pivot
*/
if ($this->manageMode == 'pivot' && isset($this->config->list)) {
2014-05-14 23:24:20 +10:00
$config = $this->makeConfig($this->config->list);
$config->model = $this->relationModel;
$config->alias = $this->alias . 'ManagePivotList';
$config->showSetup = false;
2014-10-10 22:34:57 +02:00
$config->recordOnClick = sprintf(
"$.oc.relationBehavior.clickManagePivotListRecord(:id, '%s', '%s')",
$this->field,
$this->relationGetSessionKey()
);
2014-05-14 23:24:20 +10:00
$widget = $this->makeWidget('Backend\Widgets\Lists', $config);
2014-11-04 17:41:48 +11:00
}
2014-05-14 23:24:20 +10:00
/*
* List
*/
2014-11-04 17:41:48 +11:00
elseif ($this->manageMode == 'list' && isset($this->config->list)) {
2014-05-14 23:24:20 +10:00
$config = $this->makeConfig($this->config->list);
$config->model = $this->relationModel;
$config->alias = $this->alias . 'ManageList';
$config->showSetup = false;
$config->showCheckboxes = true;
2014-09-06 12:51:39 +10:00
$config->showSorting = $this->getConfig('manage[showSorting]', true);
$config->defaultSort = $this->getConfig('manage[defaultSort]');
$config->recordsPerPage = $this->getConfig('manage[recordsPerPage]');
if ($this->viewMode == 'single') {
$config->showCheckboxes = false;
$config->recordOnClick = sprintf(
"$.oc.relationBehavior.clickManageListRecord(:id, '%s', '%s')",
$this->field,
$this->relationGetSessionKey()
);
}
2014-05-14 23:24:20 +10:00
$widget = $this->makeWidget('Backend\Widgets\Lists', $config);
/*
* Link the Search Widget to the List Widget
*/
if ($this->getConfig('manage[showSearch]')) {
$this->searchWidget = $this->makeSearchWidget();
$this->searchWidget->bindToController();
2014-10-10 22:34:57 +02:00
$this->searchWidget->bindEvent('search.submit', function () use ($widget) {
$widget->setSearchTerm($this->searchWidget->getActiveTerm());
return $widget->onRefresh();
});
$this->searchWidget->setActiveTerm(null);
}
2014-11-04 17:41:48 +11:00
}
2014-05-14 23:24:20 +10:00
/*
* Form
*/
2014-11-04 17:41:48 +11:00
elseif ($this->manageMode == 'form' && isset($this->config->form)) {
2014-05-14 23:24:20 +10:00
$config = $this->makeConfig($this->config->form);
$config->model = $this->relationModel;
2014-09-29 13:12:34 +10:00
$config->arrayName = class_basename($this->relationModel);
2014-05-14 23:24:20 +10:00
$config->context = 'relation';
$config->alias = $this->alias . 'ManageForm';
/*
* Existing record
*/
if ($this->manageId) {
$config->model = $config->model->find($this->manageId);
if (!$config->model) {
throw new ApplicationException(Lang::get('backend::lang.model.not_found', [
'class' => get_class($config->model), 'id' => $this->manageId
]));
}
}
$widget = $this->makeWidget('Backend\Widgets\Form', $config);
}
2014-10-10 22:34:57 +02:00
if (!$widget) {
return null;
2014-10-10 22:34:57 +02:00
}
2014-05-14 23:24:20 +10:00
/*
2014-05-17 18:08:01 +02:00
* Exclude existing relationships
2014-05-14 23:24:20 +10:00
*/
if ($this->manageMode == 'pivot' || $this->manageMode == 'list') {
2014-10-10 22:34:57 +02:00
$widget->bindEvent('list.extendQuery', function ($query) {
$this->controller->relationExtendQuery($query, $this->field);
2014-05-14 23:24:20 +10:00
/*
* Where not in the current list of related records
*/
$existingIds = $this->findExistingRelationIds();
if (count($existingIds)) {
2014-07-07 19:50:07 +10:00
$query->whereNotIn($this->relationModel->getQualifiedKeyName(), $existingIds);
2014-05-14 23:24:20 +10:00
}
});
}
return $widget;
}
protected function makePivotWidget()
{
$config = $this->makeConfig($this->config->pivot);
$config->model = $this->relationModel;
2014-09-29 13:12:34 +10:00
$config->arrayName = class_basename($this->relationModel);
2014-05-14 23:24:20 +10:00
$config->context = 'relation';
$config->alias = $this->alias . 'ManagePivotForm';
/*
* Existing record
*/
if ($this->manageId) {
$relations = $this->model->{$this->field};
$config->model = $relations->find($this->manageId);
if (!$config->model) {
throw new ApplicationException(Lang::get('backend::lang.model.not_found', [
'class' => get_class($config->model), 'id' => $this->manageId
]));
}
$config->data = $config->model->pivot;
}
$widget = $this->makeWidget('Backend\Widgets\Form', $config);
return $widget;
}
/**
* Returns the active session key.
*/
public function relationGetSessionKey($force = false)
{
2014-10-10 22:34:57 +02:00
if ($this->sessionKey && !$force) {
return $this->sessionKey;
2014-10-10 22:34:57 +02:00
}
2014-10-10 22:34:57 +02:00
if (post('_relation_session_key')) {
return $this->sessionKey = post('_relation_session_key');
2014-10-10 22:34:57 +02:00
}
2014-10-10 22:34:57 +02:00
if (post('_session_key')) {
return $this->sessionKey = post('_session_key');
2014-10-10 22:34:57 +02:00
}
return $this->sessionKey = FormHelper::getSessionKey();
}
2014-10-10 22:34:57 +02:00
}