2014-07-02 10:48:45 +00:00
|
|
|
<?php namespace Backend\FormWidgets;
|
|
|
|
|
|
2014-08-01 08:14:39 +00:00
|
|
|
use Lang;
|
2015-03-19 09:00:31 +00:00
|
|
|
use ApplicationException;
|
2014-07-02 10:48:45 +00:00
|
|
|
use Backend\Classes\FormWidgetBase;
|
|
|
|
|
|
|
|
|
|
/**
|
2014-08-01 08:14:39 +00:00
|
|
|
* Record Finder
|
2014-07-02 10:48:45 +00:00
|
|
|
* Renders a record finder field.
|
|
|
|
|
*
|
|
|
|
|
* user:
|
|
|
|
|
* label: User
|
|
|
|
|
* type: recordfinder
|
2015-02-07 05:20:34 +00:00
|
|
|
* list: ~/plugins/rainlab/user/models/user/columns.yaml
|
2015-11-01 18:39:26 +00:00
|
|
|
* title: Find Record
|
2014-07-02 10:48:45 +00:00
|
|
|
* prompt: Click the Find button to find a user
|
2014-09-17 08:39:09 +00:00
|
|
|
* nameFrom: name
|
|
|
|
|
* descriptionFrom: email
|
2016-02-10 10:45:21 +00:00
|
|
|
*
|
2014-07-02 10:48:45 +00:00
|
|
|
* @package october\backend
|
|
|
|
|
* @author Alexey Bobkov, Samuel Georges
|
|
|
|
|
*/
|
|
|
|
|
class RecordFinder extends FormWidgetBase
|
|
|
|
|
{
|
2016-03-25 07:01:58 +00:00
|
|
|
use \Backend\Traits\FormModelWidget;
|
|
|
|
|
|
2015-02-28 03:43:34 +00:00
|
|
|
//
|
|
|
|
|
// Configurable properties
|
|
|
|
|
//
|
|
|
|
|
|
2014-07-02 10:48:45 +00:00
|
|
|
/**
|
2015-02-28 03:43:34 +00:00
|
|
|
* @var string Field name to use for key.
|
2014-07-02 10:48:45 +00:00
|
|
|
*/
|
2015-02-28 03:43:34 +00:00
|
|
|
public $keyFrom = 'id';
|
2014-07-02 10:48:45 +00:00
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
/**
|
2015-02-28 03:43:34 +00:00
|
|
|
* @var string Relation column to display for the name
|
2014-07-03 08:35:35 +00:00
|
|
|
*/
|
2015-02-28 03:43:34 +00:00
|
|
|
public $nameFrom;
|
2014-07-03 08:35:35 +00:00
|
|
|
|
|
|
|
|
/**
|
2015-02-28 03:43:34 +00:00
|
|
|
* @var string Relation column to display for the description
|
2014-07-03 08:35:35 +00:00
|
|
|
*/
|
2015-02-28 03:43:34 +00:00
|
|
|
public $descriptionFrom;
|
2014-07-03 08:35:35 +00:00
|
|
|
|
2015-11-01 18:39:26 +00:00
|
|
|
/**
|
|
|
|
|
* @var string Text to display for the title of the popup list form
|
|
|
|
|
*/
|
|
|
|
|
public $title = 'backend::lang.recordfinder.find_record';
|
|
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
/**
|
2015-02-28 03:43:34 +00:00
|
|
|
* @var string Prompt to display if no record is selected.
|
2014-07-03 08:35:35 +00:00
|
|
|
*/
|
2015-02-28 03:43:34 +00:00
|
|
|
public $prompt = 'Click the %s button to find a record';
|
|
|
|
|
|
2016-06-11 03:36:54 +00:00
|
|
|
/**
|
|
|
|
|
* @var int Maximum rows to display for each page.
|
|
|
|
|
*/
|
|
|
|
|
public $recordsPerPage = 10;
|
|
|
|
|
|
2016-04-20 19:36:29 +00:00
|
|
|
/**
|
|
|
|
|
* @var string Use a custom scope method for the list query.
|
|
|
|
|
*/
|
|
|
|
|
public $scope;
|
|
|
|
|
|
2015-08-15 19:34:28 +00:00
|
|
|
/**
|
|
|
|
|
* @var string Filters the relation using a raw where query statement.
|
|
|
|
|
*/
|
|
|
|
|
public $conditions;
|
|
|
|
|
|
2016-04-20 19:36:29 +00:00
|
|
|
/**
|
|
|
|
|
* @var string If searching the records, specifies a policy to use.
|
|
|
|
|
* - all: result must contain all words
|
|
|
|
|
* - any: result can contain any word
|
|
|
|
|
* - exact: result must contain the exact phrase
|
|
|
|
|
*/
|
|
|
|
|
public $searchMode;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var string Use a custom scope method for performing searches.
|
|
|
|
|
*/
|
|
|
|
|
public $searchScope;
|
|
|
|
|
|
2015-02-28 03:43:34 +00:00
|
|
|
//
|
|
|
|
|
// Object properties
|
|
|
|
|
//
|
2014-07-03 08:35:35 +00:00
|
|
|
|
|
|
|
|
/**
|
2017-03-15 19:26:14 +00:00
|
|
|
* @inheritDoc
|
2014-07-03 08:35:35 +00:00
|
|
|
*/
|
2015-02-28 03:43:34 +00:00
|
|
|
protected $defaultAlias = 'recordfinder';
|
2014-07-03 08:35:35 +00:00
|
|
|
|
|
|
|
|
/**
|
2015-02-28 03:43:34 +00:00
|
|
|
* @var Model Relationship model
|
2014-07-03 08:35:35 +00:00
|
|
|
*/
|
2015-02-28 03:43:34 +00:00
|
|
|
public $relationModel;
|
2014-07-03 08:35:35 +00:00
|
|
|
|
|
|
|
|
/**
|
2015-08-15 19:34:28 +00:00
|
|
|
* @var \Backend\Classes\WidgetBase Reference to the widget used for viewing (list or form).
|
2014-07-03 08:35:35 +00:00
|
|
|
*/
|
|
|
|
|
protected $listWidget;
|
2014-07-02 10:48:45 +00:00
|
|
|
|
2014-07-08 08:21:40 +00:00
|
|
|
/**
|
2015-08-15 19:34:28 +00:00
|
|
|
* @var \Backend\Classes\WidgetBase Reference to the widget used for searching.
|
2014-07-08 08:21:40 +00:00
|
|
|
*/
|
|
|
|
|
protected $searchWidget;
|
|
|
|
|
|
2014-07-02 10:48:45 +00:00
|
|
|
/**
|
2017-03-15 19:26:14 +00:00
|
|
|
* @inheritDoc
|
2014-07-02 10:48:45 +00:00
|
|
|
*/
|
|
|
|
|
public function init()
|
|
|
|
|
{
|
2015-02-28 03:43:34 +00:00
|
|
|
$this->fillFromConfig([
|
2015-11-01 18:39:26 +00:00
|
|
|
'title',
|
2015-02-28 03:43:34 +00:00
|
|
|
'prompt',
|
|
|
|
|
'keyFrom',
|
|
|
|
|
'nameFrom',
|
|
|
|
|
'descriptionFrom',
|
2016-04-20 19:36:29 +00:00
|
|
|
'scope',
|
2015-08-15 19:34:28 +00:00
|
|
|
'conditions',
|
2016-04-20 19:36:29 +00:00
|
|
|
'searchMode',
|
|
|
|
|
'searchScope',
|
2016-06-11 03:36:54 +00:00
|
|
|
'recordsPerPage',
|
2015-02-28 03:43:34 +00:00
|
|
|
]);
|
|
|
|
|
|
2017-03-21 22:07:51 +00:00
|
|
|
if ($this->formField->disabled) {
|
|
|
|
|
$this->previewMode = true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
if (post('recordfinder_flag')) {
|
|
|
|
|
$this->listWidget = $this->makeListWidget();
|
2014-07-08 08:21:40 +00:00
|
|
|
$this->listWidget->bindToController();
|
|
|
|
|
|
|
|
|
|
$this->searchWidget = $this->makeSearchWidget();
|
|
|
|
|
$this->searchWidget->bindToController();
|
|
|
|
|
|
2016-07-30 01:46:36 +00:00
|
|
|
$this->listWidget->setSearchTerm($this->searchWidget->getActiveTerm());
|
|
|
|
|
|
2014-07-08 08:21:40 +00:00
|
|
|
/*
|
|
|
|
|
* Link the Search Widget to the List Widget
|
|
|
|
|
*/
|
2014-10-10 21:50:05 +00:00
|
|
|
$this->searchWidget->bindEvent('search.submit', function () {
|
2014-07-08 08:21:40 +00:00
|
|
|
$this->listWidget->setSearchTerm($this->searchWidget->getActiveTerm());
|
|
|
|
|
return $this->listWidget->onRefresh();
|
|
|
|
|
});
|
2014-07-03 08:35:35 +00:00
|
|
|
}
|
2014-07-02 10:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-03-15 19:26:14 +00:00
|
|
|
* @inheritDoc
|
2014-07-02 10:48:45 +00:00
|
|
|
*/
|
|
|
|
|
public function render()
|
|
|
|
|
{
|
|
|
|
|
$this->prepareVars();
|
|
|
|
|
return $this->makePartial('container');
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
public function onRefresh()
|
|
|
|
|
{
|
2015-01-05 00:18:43 +00:00
|
|
|
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
2016-11-27 20:50:06 +00:00
|
|
|
$model->{$attribute} = post($this->getFieldName());
|
2014-09-17 09:46:49 +00:00
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
$this->prepareVars();
|
|
|
|
|
return ['#'.$this->getId('container') => $this->makePartial('recordfinder')];
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 22:07:51 +00:00
|
|
|
public function onClearRecord()
|
|
|
|
|
{
|
|
|
|
|
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
|
|
|
$model->{$attribute} = null;
|
|
|
|
|
|
|
|
|
|
$this->prepareVars();
|
|
|
|
|
return ['#'.$this->getId('container') => $this->makePartial('recordfinder')];
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-02 10:48:45 +00:00
|
|
|
/**
|
|
|
|
|
* Prepares the list data
|
|
|
|
|
*/
|
|
|
|
|
public function prepareVars()
|
|
|
|
|
{
|
2015-01-04 22:45:04 +00:00
|
|
|
$this->relationModel = $this->getLoadValue();
|
2017-06-22 15:45:29 +00:00
|
|
|
|
|
|
|
|
if ($this->formField->disabled) {
|
|
|
|
|
$this->previewMode = true;
|
|
|
|
|
}
|
2014-09-17 09:46:49 +00:00
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
$this->vars['value'] = $this->getKeyValue();
|
|
|
|
|
$this->vars['field'] = $this->formField;
|
|
|
|
|
$this->vars['nameValue'] = $this->getNameValue();
|
|
|
|
|
$this->vars['descriptionValue'] = $this->getDescriptionValue();
|
|
|
|
|
$this->vars['listWidget'] = $this->listWidget;
|
2014-07-08 08:21:40 +00:00
|
|
|
$this->vars['searchWidget'] = $this->searchWidget;
|
2015-11-28 00:24:34 +00:00
|
|
|
$this->vars['title'] = $this->title;
|
2015-07-18 16:34:30 +00:00
|
|
|
$this->vars['prompt'] = str_replace('%s', '<i class="icon-th-list"></i>', e(trans($this->prompt)));
|
2014-07-02 10:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-03-15 19:26:14 +00:00
|
|
|
* @inheritDoc
|
2014-07-02 10:48:45 +00:00
|
|
|
*/
|
2015-08-04 09:32:51 +00:00
|
|
|
protected function loadAssets()
|
2014-07-02 10:48:45 +00:00
|
|
|
{
|
2014-07-03 08:35:35 +00:00
|
|
|
$this->addJs('js/recordfinder.js', 'core');
|
2014-07-02 10:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-03-15 19:26:14 +00:00
|
|
|
* @inheritDoc
|
2014-07-02 10:48:45 +00:00
|
|
|
*/
|
2015-01-04 22:43:39 +00:00
|
|
|
public function getSaveValue($value)
|
2014-07-02 10:48:45 +00:00
|
|
|
{
|
2014-07-03 08:35:35 +00:00
|
|
|
return strlen($value) ? $value : null;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-05 01:54:14 +00:00
|
|
|
/**
|
2017-03-15 19:26:14 +00:00
|
|
|
* @inheritDoc
|
2015-01-05 01:54:14 +00:00
|
|
|
*/
|
|
|
|
|
public function getLoadValue()
|
|
|
|
|
{
|
|
|
|
|
list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom);
|
|
|
|
|
|
|
|
|
|
if (!is_null($model)) {
|
|
|
|
|
return $model->{$attribute};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
public function getKeyValue()
|
|
|
|
|
{
|
2014-10-10 21:50:05 +00:00
|
|
|
if (!$this->relationModel) {
|
2014-07-03 08:35:35 +00:00
|
|
|
return null;
|
2014-10-10 21:50:05 +00:00
|
|
|
}
|
2014-07-03 08:35:35 +00:00
|
|
|
|
2014-09-17 09:49:42 +00:00
|
|
|
return $this->relationModel->{$this->keyFrom};
|
2014-07-03 08:35:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getNameValue()
|
|
|
|
|
{
|
2014-10-10 21:50:05 +00:00
|
|
|
if (!$this->relationModel || !$this->nameFrom) {
|
2014-07-03 08:35:35 +00:00
|
|
|
return null;
|
2014-10-10 21:50:05 +00:00
|
|
|
}
|
2014-07-03 08:35:35 +00:00
|
|
|
|
2014-09-17 08:39:09 +00:00
|
|
|
return $this->relationModel->{$this->nameFrom};
|
2014-07-03 08:35:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getDescriptionValue()
|
|
|
|
|
{
|
2014-10-10 21:50:05 +00:00
|
|
|
if (!$this->relationModel || !$this->descriptionFrom) {
|
2014-07-03 08:35:35 +00:00
|
|
|
return null;
|
2014-10-10 21:50:05 +00:00
|
|
|
}
|
2014-07-03 08:35:35 +00:00
|
|
|
|
2014-09-17 08:39:09 +00:00
|
|
|
return $this->relationModel->{$this->descriptionFrom};
|
2014-07-03 08:35:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function onFindRecord()
|
|
|
|
|
{
|
|
|
|
|
$this->prepareVars();
|
2016-07-30 01:46:36 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Purge the search term stored in session
|
|
|
|
|
*/
|
|
|
|
|
if ($this->searchWidget) {
|
|
|
|
|
$this->listWidget->setSearchTerm(null);
|
|
|
|
|
$this->searchWidget->setActiveTerm(null);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-28 00:24:34 +00:00
|
|
|
return $this->makePartial('recordfinder_form');
|
2014-07-03 08:35:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function makeListWidget()
|
|
|
|
|
{
|
|
|
|
|
$config = $this->makeConfig($this->getConfig('list'));
|
2015-03-19 09:00:31 +00:00
|
|
|
$config->model = $this->getRelationModel();
|
2014-07-03 08:35:35 +00:00
|
|
|
$config->alias = $this->alias . 'List';
|
|
|
|
|
$config->showSetup = false;
|
|
|
|
|
$config->showCheckboxes = false;
|
2016-06-11 03:36:54 +00:00
|
|
|
$config->recordsPerPage = $this->recordsPerPage;
|
2016-02-10 10:45:21 +00:00
|
|
|
$config->recordOnClick = sprintf("$('#%s').recordFinder('updateRecord', this, ':" . $this->keyFrom . "')", $this->getId());
|
2014-07-03 08:35:35 +00:00
|
|
|
$widget = $this->makeWidget('Backend\Widgets\Lists', $config);
|
|
|
|
|
|
2016-04-20 19:36:29 +00:00
|
|
|
$widget->setSearchOptions([
|
|
|
|
|
'mode' => $this->searchMode,
|
|
|
|
|
'scope' => $this->searchScope,
|
|
|
|
|
]);
|
2014-07-03 08:35:35 +00:00
|
|
|
|
2016-05-16 19:17:40 +00:00
|
|
|
if ($sqlConditions = $this->conditions) {
|
2017-04-24 11:38:19 +00:00
|
|
|
$widget->bindEvent('list.extendQueryBefore', function ($query) use ($sqlConditions) {
|
2016-05-16 19:17:40 +00:00
|
|
|
$query->whereRaw($sqlConditions);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
elseif ($scopeMethod = $this->scope) {
|
2017-04-24 11:38:19 +00:00
|
|
|
$widget->bindEvent('list.extendQueryBefore', function ($query) use ($scopeMethod) {
|
Pass current model to record finder scope method
This improves the extensibility of the record finder form widget by passing the current model to the query scope that will be applied to the records being displayed. It allows the use of attributes of the current model in the query scope applied to the records being displayed as options to select.
In my use case, I have a main Survey model with related Field models. Field models can have parents and children for a tree structure, but I only want fields to have parents and children that are:
**a) Not the main record itself**
**and b) Members of / related to the same Survey model**
By passing the current model to my query scope, I can filter out ineligible records like so:
```
/**
* Limit results to only records that are eligible to be parents of the provided model
*
* @param Query $query
* @param Model $model The model to check for eligible parents agains
* @return Query
*/
public function scopeEligibleParents($query, $model) {
return $query->where('id', '!=', $model->id)
->where('parent_id', '!=', $model->id)
->where('survey_id', '=', $model->survey_id);
}
```
2016-10-11 23:15:40 +00:00
|
|
|
$query->$scopeMethod($this->model);
|
2016-04-20 19:36:29 +00:00
|
|
|
});
|
|
|
|
|
}
|
2016-05-16 19:17:40 +00:00
|
|
|
else {
|
2017-04-24 11:38:19 +00:00
|
|
|
$widget->bindEvent('list.extendQueryBefore', function ($query) {
|
2016-05-16 19:17:40 +00:00
|
|
|
$this->getRelationObject()->addDefinedConstraintsToQuery($query);
|
2015-08-15 19:34:28 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-03 08:35:35 +00:00
|
|
|
return $widget;
|
2014-07-02 10:48:45 +00:00
|
|
|
}
|
2014-07-08 08:21:40 +00:00
|
|
|
|
|
|
|
|
protected function makeSearchWidget()
|
|
|
|
|
{
|
|
|
|
|
$config = $this->makeConfig();
|
|
|
|
|
$config->alias = $this->alias . 'Search';
|
|
|
|
|
$config->growable = false;
|
2014-09-06 03:18:55 +00:00
|
|
|
$config->prompt = 'backend::lang.list.search_prompt';
|
2014-07-08 08:21:40 +00:00
|
|
|
$widget = $this->makeWidget('Backend\Widgets\Search', $config);
|
|
|
|
|
$widget->cssClasses[] = 'recordfinder-search';
|
|
|
|
|
return $widget;
|
|
|
|
|
}
|
2014-10-10 21:50:05 +00:00
|
|
|
}
|