1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace SleepingOwl\Admin\Form\Element; |
4
|
|
|
|
5
|
|
|
use Illuminate\Http\Request; |
6
|
|
|
use Illuminate\Routing\Router; |
7
|
|
|
use SleepingOwl\Admin\Contracts\Initializable; |
8
|
|
|
use SleepingOwl\Admin\Contracts\WithRoutesInterface; |
9
|
|
|
use Illuminate\Database\Eloquent\Relations\HasOneOrMany; |
10
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany; |
11
|
|
|
use SleepingOwl\Admin\Contracts\Repositories\RepositoryInterface; |
12
|
|
|
|
13
|
|
|
class MultiSelectAjax extends MultiSelect implements Initializable, WithRoutesInterface |
14
|
|
|
{ |
15
|
|
|
protected $view = 'form.element.selectajax'; |
16
|
|
|
|
17
|
|
|
protected static $route = 'multiselectajax'; |
18
|
|
|
|
19
|
|
|
protected $search_url = null; |
20
|
|
|
|
21
|
|
|
protected $min_symbols = 3; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* MultiSelectAjax constructor. |
25
|
|
|
* @param string $path |
26
|
|
|
* @param null $label |
27
|
|
|
* @param array $options |
28
|
|
|
*/ |
29
|
|
View Code Duplication |
public function __construct($path, $label = null, $options = []) |
|
|
|
|
30
|
|
|
{ |
31
|
|
|
parent::__construct($path, $label, $options); |
32
|
|
|
|
33
|
|
|
$this->setLoadOptionsQueryPreparer(function ($item, $query) { |
34
|
|
|
$repository = app(RepositoryInterface::class); |
35
|
|
|
$repository->setModel($this->getModelForOptions()); |
36
|
|
|
$key = $repository->getModel()->getKeyName(); |
37
|
|
|
|
38
|
|
|
return $query->whereIn($key, $this->getValueFromModel() ? $this->getValueFromModel() : []); |
39
|
|
|
}); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Get Field name for search url. |
44
|
|
|
* @return mixed |
45
|
|
|
*/ |
46
|
|
|
public function getFieldName() |
47
|
|
|
{ |
48
|
|
|
return str_replace('[]', '', $this->getName()); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Search url for ajax. |
53
|
|
|
* @param $url |
54
|
|
|
* @return $this |
55
|
|
|
*/ |
56
|
|
|
public function setSearchUrl($url) |
57
|
|
|
{ |
58
|
|
|
$this->search_url = $url; |
59
|
|
|
|
60
|
|
|
return $this; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Getter of search url. |
65
|
|
|
* @return string |
66
|
|
|
*/ |
67
|
|
View Code Duplication |
public function getSearchUrl() |
|
|
|
|
68
|
|
|
{ |
69
|
|
|
return $this->search_url ? $this->search_url : route('admin.form.element.'.static::$route, [ |
70
|
|
|
'adminModel' => \AdminSection::getModel($this->model)->getAlias(), |
71
|
|
|
'field' => $this->getFieldName(), |
72
|
|
|
'id' => $this->model->getKey(), |
73
|
|
|
]); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param Router $router |
78
|
|
|
*/ |
79
|
285 |
View Code Duplication |
public static function registerRoutes(Router $router) |
|
|
|
|
80
|
|
|
{ |
81
|
285 |
|
$routeName = 'admin.form.element.'.static::$route; |
82
|
|
|
|
83
|
285 |
|
if (! $router->has($routeName)) { |
84
|
285 |
|
$router->post('{adminModel}/'.static::$route.'/{field}/{id?}', [ |
85
|
285 |
|
'as' => $routeName, |
86
|
285 |
|
'uses' => 'SleepingOwl\Admin\Http\Controllers\FormElementController@multiselectSearch', |
87
|
285 |
|
]); |
88
|
285 |
|
} |
89
|
285 |
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Set min symbols to search. |
93
|
|
|
* @param $symbols |
94
|
|
|
* @return $this |
95
|
|
|
*/ |
96
|
|
|
public function setMinSymbols($symbols) |
97
|
|
|
{ |
98
|
|
|
$this->min_symbols = $symbols; |
99
|
|
|
|
100
|
|
|
return $this; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Get min symbols to search. |
105
|
|
|
* @return int |
106
|
|
|
*/ |
107
|
|
|
public function getMinSymbols() |
108
|
|
|
{ |
109
|
|
|
return $this->min_symbols; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @return array |
114
|
|
|
*/ |
115
|
|
View Code Duplication |
public function toArray() |
|
|
|
|
116
|
|
|
{ |
117
|
|
|
$this->setHtmlAttributes([ |
118
|
|
|
'id' => $this->getName(), |
119
|
|
|
'class' => 'form-control js-data-ajax', |
120
|
|
|
'multiple', |
121
|
|
|
'field' => $this->display, |
122
|
|
|
'model' => get_class($this->getModelForOptions()), |
123
|
|
|
'search_url' => $this->getSearchUrl(), |
124
|
|
|
'data-min-symbols' => $this->getMinSymbols(), |
125
|
|
|
]); |
126
|
|
|
|
127
|
|
|
return ['attributes' => $this->getHtmlAttributes()] + parent::toArray(); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @return array |
132
|
|
|
*/ |
133
|
|
|
protected function loadOptions() |
134
|
|
|
{ |
135
|
|
|
$repository = app(RepositoryInterface::class); |
136
|
|
|
$repository->setModel($this->getModelForOptions()); |
137
|
|
|
$key = $repository->getModel()->getKeyName(); |
138
|
|
|
|
139
|
|
|
$options = $repository->getQuery(); |
140
|
|
|
$relation = $this->getModelAttributeKey(); |
141
|
|
|
|
142
|
|
View Code Duplication |
if ($this->isEmptyRelation() and ! is_null($foreignKey = $this->getForeignKey())) { |
|
|
|
|
143
|
|
|
$model = $this->getModel(); |
144
|
|
|
|
145
|
|
|
if ($model->{$relation}() instanceof HasOneOrMany) { |
146
|
|
|
$options->where($foreignKey, 0)->orWhereNull($foreignKey); |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
|
150
|
|
View Code Duplication |
if (count($this->getFetchColumns()) > 0) { |
|
|
|
|
151
|
|
|
$options->select( |
152
|
|
|
array_merge([$key], $this->getFetchColumns()) |
153
|
|
|
); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
// call the pre load options query preparer if has be set |
157
|
|
|
if (! is_null($preparer = $this->getLoadOptionsQueryPreparer())) { |
158
|
|
|
$options = $preparer($this, $options); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
if (method_exists($this->getModel(), $relation) && $this->getModel()->{$relation}() instanceof BelongsToMany) { |
162
|
|
|
$options = $this->getModel()->{$relation}(); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
$options = $options->get(); |
166
|
|
|
|
167
|
|
View Code Duplication |
if (is_callable($makeDisplay = $this->getDisplay())) { |
|
|
|
|
168
|
|
|
// make dynamic display text |
169
|
|
|
if ($options instanceof Collection) { |
|
|
|
|
170
|
|
|
$options = $options->all(); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
// iterate for all options and redefine it as |
174
|
|
|
// list of KEY and TEXT pair |
175
|
|
|
$options = array_map(function ($opt) use ($key, $makeDisplay) { |
176
|
|
|
// get the KEY and make the display text |
177
|
|
|
return [data_get($opt, $key), $makeDisplay($opt)]; |
178
|
|
|
}, $options); |
179
|
|
|
|
180
|
|
|
// take options as array with KEY => VALUE pair |
181
|
|
|
$options = array_pluck($options, 1, 0); |
182
|
|
|
} elseif ($options instanceof Collection) { |
|
|
|
|
183
|
|
|
// take options as array with KEY => VALUE pair |
184
|
|
|
$options = array_pluck($options->all(), $this->getDisplay(), $key); |
185
|
|
|
} else { |
186
|
|
|
// take options as array with KEY => VALUE pair |
187
|
|
|
$options = array_pluck($options, $this->getDisplay(), $key); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
return $options; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* @param Request $request |
195
|
|
|
* |
196
|
|
|
* @return void |
197
|
|
|
*/ |
198
|
|
|
public function afterSave(Request $request) |
199
|
|
|
{ |
200
|
|
|
$attribute = $this->getModelAttributeKey(); |
201
|
|
|
|
202
|
|
|
if (! method_exists($this->getModel(), $attribute)) { |
203
|
|
|
return; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
parent::afterSave($request); |
207
|
|
|
} |
208
|
|
|
} |
209
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.