1 | <?php |
||
2 | |||
3 | namespace A17\Twill\Http\Controllers\Admin; |
||
4 | |||
5 | use A17\Twill\Helpers\FlashLevel; |
||
6 | use A17\Twill\Services\Blocks\BlockCollection; |
||
7 | use Illuminate\Contracts\Foundation\Application; |
||
8 | use Illuminate\Http\Request; |
||
9 | use Illuminate\Support\Arr; |
||
10 | use Illuminate\Support\Collection; |
||
11 | use Illuminate\Support\Facades\App; |
||
12 | use Illuminate\Support\Facades\Auth; |
||
13 | use Illuminate\Support\Facades\Config; |
||
14 | use Illuminate\Support\Facades\Redirect; |
||
15 | use Illuminate\Support\Facades\Response; |
||
16 | use Illuminate\Support\Facades\Route; |
||
17 | use Illuminate\Support\Facades\Session; |
||
18 | use Illuminate\Support\Facades\URL; |
||
19 | use Illuminate\Support\Facades\View; |
||
20 | use Illuminate\Support\Str; |
||
21 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
||
22 | |||
23 | abstract class ModuleController extends Controller |
||
24 | { |
||
25 | /** |
||
26 | * @var Application |
||
27 | */ |
||
28 | protected $app; |
||
29 | |||
30 | /** |
||
31 | * @var Request |
||
32 | */ |
||
33 | protected $request; |
||
34 | |||
35 | /** |
||
36 | * @var string |
||
37 | */ |
||
38 | protected $namespace; |
||
39 | |||
40 | /** |
||
41 | * @var string |
||
42 | */ |
||
43 | protected $routePrefix; |
||
44 | |||
45 | /** |
||
46 | * @var string |
||
47 | */ |
||
48 | protected $moduleName; |
||
49 | |||
50 | /** |
||
51 | * @var string |
||
52 | */ |
||
53 | protected $modelName; |
||
54 | |||
55 | /** |
||
56 | * @var string |
||
57 | */ |
||
58 | protected $modelTitle; |
||
59 | |||
60 | /** |
||
61 | * @var \A17\Twill\Repositories\ModuleRepository |
||
62 | */ |
||
63 | protected $repository; |
||
64 | |||
65 | /** |
||
66 | * Options of the index view. |
||
67 | * |
||
68 | * @var array |
||
69 | */ |
||
70 | protected $defaultIndexOptions = [ |
||
71 | 'create' => true, |
||
72 | 'edit' => true, |
||
73 | 'publish' => true, |
||
74 | 'bulkPublish' => true, |
||
75 | 'feature' => false, |
||
76 | 'bulkFeature' => false, |
||
77 | 'restore' => true, |
||
78 | 'bulkRestore' => true, |
||
79 | 'forceDelete' => true, |
||
80 | 'bulkForceDelete' => true, |
||
81 | 'delete' => true, |
||
82 | 'duplicate' => false, |
||
83 | 'bulkDelete' => true, |
||
84 | 'reorder' => false, |
||
85 | 'permalink' => true, |
||
86 | 'bulkEdit' => true, |
||
87 | 'editInModal' => false, |
||
88 | 'skipCreateModal' => false, |
||
89 | ]; |
||
90 | |||
91 | /** |
||
92 | * Relations to eager load for the index view |
||
93 | * |
||
94 | * @var array |
||
95 | */ |
||
96 | protected $indexWith = []; |
||
97 | |||
98 | /** |
||
99 | * Relations to eager load for the form view. |
||
100 | * |
||
101 | * @var array |
||
102 | */ |
||
103 | protected $formWith = []; |
||
104 | |||
105 | /** |
||
106 | * Relation count to eager load for the form view. |
||
107 | * |
||
108 | * @var array |
||
109 | */ |
||
110 | protected $formWithCount = []; |
||
111 | |||
112 | /** |
||
113 | * Additional filters for the index view. |
||
114 | * |
||
115 | * To automatically have your filter added to the index view use the following convention: |
||
116 | * suffix the key containing the list of items to show in the filter by 'List' and |
||
117 | * name it the same as the filter you defined in this array. |
||
118 | * |
||
119 | * Example: 'fCategory' => 'category_id' here and 'fCategoryList' in indexData() |
||
120 | * By default, this will run a where query on the category_id column with the value |
||
121 | * of fCategory if found in current request parameters. You can intercept this behavior |
||
122 | * from your repository in the filter() function. |
||
123 | * |
||
124 | * @var array |
||
125 | */ |
||
126 | protected $filters = []; |
||
127 | |||
128 | /** |
||
129 | * Additional links to display in the listing filter |
||
130 | * |
||
131 | * @var array |
||
132 | */ |
||
133 | protected $filterLinks = []; |
||
134 | |||
135 | /** |
||
136 | * Filters that are selected by default in the index view. |
||
137 | * |
||
138 | * Example: 'filter_key' => 'default_filter_value' |
||
139 | * |
||
140 | * @var array |
||
141 | */ |
||
142 | protected $filtersDefaultOptions = []; |
||
143 | |||
144 | /** |
||
145 | * Default orders for the index view. |
||
146 | * |
||
147 | * @var array |
||
148 | */ |
||
149 | protected $defaultOrders = [ |
||
150 | 'created_at' => 'desc', |
||
151 | ]; |
||
152 | |||
153 | /** |
||
154 | * @var int |
||
155 | */ |
||
156 | protected $perPage = 20; |
||
157 | |||
158 | /** |
||
159 | * Name of the index column to use as name column. |
||
160 | * |
||
161 | * @var string |
||
162 | */ |
||
163 | protected $titleColumnKey = 'title'; |
||
164 | |||
165 | /** |
||
166 | * Attribute to use as title in forms. |
||
167 | * |
||
168 | * @var string |
||
169 | */ |
||
170 | protected $titleFormKey; |
||
171 | |||
172 | /** |
||
173 | * Feature field name if the controller is using the feature route (defaults to "featured"). |
||
174 | * |
||
175 | * @var string |
||
176 | */ |
||
177 | protected $featureField = 'featured'; |
||
178 | |||
179 | /** |
||
180 | * Indicates if this module is edited through a parent module. |
||
181 | * |
||
182 | * @var bool |
||
183 | */ |
||
184 | protected $submodule = false; |
||
185 | |||
186 | /** |
||
187 | * @var int|null |
||
188 | */ |
||
189 | protected $submoduleParentId = null; |
||
190 | |||
191 | /** |
||
192 | * Can be used in child classes to disable the content editor (full screen block editor). |
||
193 | * |
||
194 | * @var bool |
||
195 | */ |
||
196 | protected $disableEditor = false; |
||
197 | |||
198 | /** |
||
199 | * @var array |
||
200 | */ |
||
201 | protected $indexOptions; |
||
202 | |||
203 | /** |
||
204 | * @var array |
||
205 | */ |
||
206 | protected $indexColumns; |
||
207 | |||
208 | /** |
||
209 | * @var array |
||
210 | */ |
||
211 | protected $browserColumns; |
||
212 | |||
213 | /** |
||
214 | * @var string |
||
215 | */ |
||
216 | protected $permalinkBase; |
||
217 | |||
218 | /** |
||
219 | * @var array |
||
220 | */ |
||
221 | protected $defaultFilters; |
||
222 | |||
223 | /** |
||
224 | * @var string |
||
225 | */ |
||
226 | protected $viewPrefix; |
||
227 | |||
228 | /** |
||
229 | * @var string |
||
230 | */ |
||
231 | protected $previewView; |
||
232 | |||
233 | /** |
||
234 | * List of permissions keyed by a request field. Can be used to prevent unauthorized field updates. |
||
235 | * |
||
236 | * @var array |
||
237 | */ |
||
238 | protected $fieldsPermissions = []; |
||
239 | |||
240 | 44 | public function __construct(Application $app, Request $request) |
|
241 | { |
||
242 | 44 | parent::__construct(); |
|
243 | 44 | $this->app = $app; |
|
244 | 44 | $this->request = $request; |
|
245 | |||
246 | 44 | $this->setMiddlewarePermission(); |
|
247 | |||
248 | 44 | $this->modelName = $this->getModelName(); |
|
249 | 44 | $this->routePrefix = $this->getRoutePrefix(); |
|
250 | 44 | $this->namespace = $this->getNamespace(); |
|
251 | 44 | $this->repository = $this->getRepository(); |
|
252 | 44 | $this->viewPrefix = $this->getViewPrefix(); |
|
253 | 44 | $this->modelTitle = $this->getModelTitle(); |
|
254 | |||
255 | /* |
||
256 | * Default filters for the index view |
||
257 | * By default, the search field will run a like query on the title field |
||
258 | */ |
||
259 | 44 | if (!isset($this->defaultFilters)) { |
|
260 | 30 | $this->defaultFilters = [ |
|
261 | 30 | 'search' => ($this->moduleHas('translations') ? '' : '%') . $this->titleColumnKey, |
|
262 | ]; |
||
263 | } |
||
264 | |||
265 | /* |
||
266 | * Apply any filters that are selected by default |
||
267 | */ |
||
268 | 44 | $this->applyFiltersDefaultOptions(); |
|
269 | |||
270 | /* |
||
271 | * Available columns of the index view |
||
272 | */ |
||
273 | 44 | if (!isset($this->indexColumns)) { |
|
274 | 15 | $this->indexColumns = [ |
|
275 | 15 | $this->titleColumnKey => [ |
|
276 | 15 | 'title' => ucfirst($this->titleColumnKey), |
|
277 | 15 | 'field' => $this->titleColumnKey, |
|
278 | 'sort' => true, |
||
279 | ], |
||
280 | ]; |
||
281 | } |
||
282 | |||
283 | /* |
||
284 | * Available columns of the browser view |
||
285 | */ |
||
286 | 44 | if (!isset($this->browserColumns)) { |
|
287 | 44 | $this->browserColumns = [ |
|
288 | 44 | $this->titleColumnKey => [ |
|
289 | 44 | 'title' => ucfirst($this->titleColumnKey), |
|
290 | 44 | 'field' => $this->titleColumnKey, |
|
291 | ], |
||
292 | ]; |
||
293 | } |
||
294 | 44 | } |
|
295 | |||
296 | /** |
||
297 | * @return void |
||
298 | */ |
||
299 | 44 | protected function setMiddlewarePermission() |
|
300 | { |
||
301 | 44 | $this->middleware('can:list', ['only' => ['index', 'show']]); |
|
302 | 44 | $this->middleware('can:edit', ['only' => ['store', 'edit', 'update']]); |
|
303 | 44 | $this->middleware('can:duplicate', ['only' => ['duplicate']]); |
|
304 | 44 | $this->middleware('can:publish', ['only' => ['publish', 'feature', 'bulkPublish', 'bulkFeature']]); |
|
305 | 44 | $this->middleware('can:reorder', ['only' => ['reorder']]); |
|
306 | 44 | $this->middleware('can:delete', ['only' => ['destroy', 'bulkDelete', 'restore', 'bulkRestore', 'forceDelete', 'bulkForceDelete', 'restoreRevision']]); |
|
307 | 44 | } |
|
308 | |||
309 | /** |
||
310 | * @param int|null $parentModuleId |
||
311 | * @return array|\Illuminate\View\View |
||
312 | */ |
||
313 | 6 | public function index($parentModuleId = null) |
|
314 | { |
||
315 | 6 | $this->submodule = isset($parentModuleId); |
|
316 | 6 | $this->submoduleParentId = $parentModuleId; |
|
317 | |||
318 | 6 | $indexData = $this->getIndexData($this->submodule ? [ |
|
319 | $this->getParentModuleForeignKey() => $this->submoduleParentId, |
||
320 | 6 | ] : []); |
|
321 | |||
322 | 6 | if ($this->request->ajax()) { |
|
323 | 3 | return $indexData + ['replaceUrl' => true]; |
|
324 | } |
||
325 | |||
326 | 3 | if ($this->request->has('openCreate') && $this->request->get('openCreate')) { |
|
327 | $indexData += ['openCreate' => true]; |
||
328 | } |
||
329 | |||
330 | 3 | $view = Collection::make([ |
|
331 | 3 | "$this->viewPrefix.index", |
|
332 | 3 | "twill::$this->moduleName.index", |
|
333 | 3 | "twill::layouts.listing", |
|
334 | ])->first(function ($view) { |
||
335 | 3 | return View::exists($view); |
|
336 | 3 | }); |
|
337 | |||
338 | 3 | return View::make($view, $indexData); |
|
339 | } |
||
340 | |||
341 | /** |
||
342 | * @return \Illuminate\Http\JsonResponse |
||
343 | */ |
||
344 | 2 | public function browser() |
|
345 | { |
||
346 | 2 | return Response::json($this->getBrowserData()); |
|
347 | } |
||
348 | |||
349 | /** |
||
350 | * @param int|null $parentModuleId |
||
351 | * @return \Illuminate\Http\JsonResponse |
||
352 | */ |
||
353 | 25 | public function store($parentModuleId = null) |
|
354 | { |
||
355 | 25 | $input = $this->validateFormRequest()->all(); |
|
356 | 25 | $optionalParent = $parentModuleId ? [$this->getParentModuleForeignKey() => $parentModuleId] : []; |
|
357 | |||
358 | 25 | if (isset($input['cmsSaveType']) && $input['cmsSaveType'] === 'cancel') { |
|
359 | return $this->respondWithRedirect(moduleRoute( |
||
360 | $this->moduleName, |
||
361 | $this->routePrefix, |
||
362 | 'create' |
||
363 | )); |
||
364 | } |
||
365 | |||
366 | 25 | $item = $this->repository->create($input + $optionalParent); |
|
367 | |||
368 | 25 | activity()->performedOn($item)->log('created'); |
|
369 | |||
370 | 25 | $this->fireEvent($input); |
|
371 | |||
372 | 25 | Session::put($this->moduleName . '_retain', true); |
|
373 | |||
374 | 25 | if ($this->getIndexOption('editInModal')) { |
|
375 | 3 | return $this->respondWithSuccess(twillTrans('twill::lang.publisher.save-success')); |
|
376 | } |
||
377 | |||
378 | 22 | if ($parentModuleId) { |
|
379 | $params = [ |
||
380 | Str::singular(explode('.', $this->moduleName)[0]) => $parentModuleId, |
||
381 | Str::singular(explode('.', $this->moduleName)[1]) => $item->id, |
||
382 | ]; |
||
383 | } else { |
||
384 | $params = [ |
||
385 | 22 | Str::singular($this->moduleName) => $item->id, |
|
386 | ]; |
||
387 | } |
||
388 | |||
389 | 22 | if (isset($input['cmsSaveType']) && Str::endsWith($input['cmsSaveType'], '-close')) { |
|
390 | return $this->respondWithRedirect($this->getBackLink()); |
||
391 | } |
||
392 | |||
393 | 22 | if (isset($input['cmsSaveType']) && Str::endsWith($input['cmsSaveType'], '-new')) { |
|
394 | return $this->respondWithRedirect(moduleRoute( |
||
395 | $this->moduleName, |
||
396 | $this->routePrefix, |
||
397 | 'create' |
||
398 | )); |
||
399 | } |
||
400 | |||
401 | 22 | return $this->respondWithRedirect(moduleRoute( |
|
402 | 22 | $this->moduleName, |
|
403 | 22 | $this->routePrefix, |
|
404 | 22 | 'edit', |
|
405 | $params |
||
406 | )); |
||
407 | } |
||
408 | |||
409 | /** |
||
410 | * @param int|$id |
||
411 | * @param int|null $submoduleId |
||
412 | * @return \Illuminate\Http\RedirectResponse |
||
413 | */ |
||
414 | 1 | public function show($id, $submoduleId = null) |
|
415 | { |
||
416 | 1 | if ($this->getIndexOption('editInModal')) { |
|
417 | return Redirect::to(moduleRoute($this->moduleName, $this->routePrefix, 'index')); |
||
418 | } |
||
419 | |||
420 | 1 | return $this->redirectToForm($submoduleId ?? $id); |
|
421 | } |
||
422 | |||
423 | /** |
||
424 | * @param int $id |
||
425 | * @param int|null $submoduleId |
||
426 | * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\View\View |
||
427 | */ |
||
428 | 6 | public function edit($id, $submoduleId = null) |
|
429 | { |
||
430 | 6 | $this->submodule = isset($submoduleId); |
|
431 | 6 | $this->submoduleParentId = $id; |
|
432 | |||
433 | 6 | if ($this->getIndexOption('editInModal')) { |
|
434 | 2 | return $this->request->ajax() |
|
435 | 1 | ? Response::json($this->modalFormData($submoduleId ?? $id)) |
|
436 | 2 | : Redirect::to(moduleRoute($this->moduleName, $this->routePrefix, 'index')); |
|
437 | } |
||
438 | |||
439 | 4 | $this->setBackLink(); |
|
440 | |||
441 | 4 | $view = Collection::make([ |
|
442 | 4 | "$this->viewPrefix.form", |
|
443 | 4 | "twill::$this->moduleName.form", |
|
444 | 4 | "twill::layouts.form", |
|
445 | ])->first(function ($view) { |
||
446 | 4 | return View::exists($view); |
|
447 | 4 | }); |
|
448 | |||
449 | 4 | return View::make($view, $this->form($submoduleId ?? $id)); |
|
450 | } |
||
451 | |||
452 | /** |
||
453 | * @param int $id |
||
454 | * @param int|null $submoduleId |
||
455 | * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\View\View |
||
456 | */ |
||
457 | public function create() |
||
458 | { |
||
459 | if (!$this->getIndexOption('skipCreateModal')) { |
||
460 | return Redirect::to(moduleRoute( |
||
461 | $this->moduleName, |
||
462 | $this->routePrefix, |
||
463 | 'index', |
||
464 | ['openCreate' => true] |
||
465 | )); |
||
466 | } |
||
467 | |||
468 | $view = Collection::make([ |
||
469 | "$this->viewPrefix.form", |
||
470 | "twill::$this->moduleName.form", |
||
471 | "twill::layouts.form", |
||
472 | ])->first(function ($view) { |
||
473 | return View::exists($view); |
||
474 | }); |
||
475 | |||
476 | return View::make($view, $this->form(null)); |
||
477 | } |
||
478 | |||
479 | /** |
||
480 | * @param int $id |
||
481 | * @param int|null $submoduleId |
||
482 | * @return \Illuminate\Http\JsonResponse |
||
483 | */ |
||
484 | 8 | public function update($id, $submoduleId = null) |
|
485 | { |
||
486 | 8 | $this->submodule = isset($submoduleId); |
|
487 | 8 | $this->submoduleParentId = $id; |
|
488 | |||
489 | 8 | $item = $this->repository->getById($submoduleId ?? $id); |
|
490 | 8 | $input = $this->request->all(); |
|
491 | |||
492 | 8 | if (isset($input['cmsSaveType']) && $input['cmsSaveType'] === 'cancel') { |
|
493 | return $this->respondWithRedirect(moduleRoute( |
||
494 | $this->moduleName, |
||
495 | $this->routePrefix, |
||
496 | 'edit', |
||
497 | [Str::singular($this->moduleName) => $id] |
||
498 | )); |
||
499 | } else { |
||
500 | 8 | $formRequest = $this->validateFormRequest(); |
|
501 | |||
502 | 8 | $this->repository->update($submoduleId ?? $id, $formRequest->all()); |
|
503 | |||
504 | 8 | activity()->performedOn($item)->log('updated'); |
|
505 | |||
506 | 8 | $this->fireEvent(); |
|
507 | |||
508 | 8 | if (isset($input['cmsSaveType'])) { |
|
509 | 8 | if (Str::endsWith($input['cmsSaveType'], '-close')) { |
|
510 | return $this->respondWithRedirect($this->getBackLink()); |
||
511 | 8 | } elseif (Str::endsWith($input['cmsSaveType'], '-new')) { |
|
512 | if ($this->getIndexOption('skipCreateModal')) { |
||
513 | return $this->respondWithRedirect(moduleRoute( |
||
514 | $this->moduleName, |
||
515 | $this->routePrefix, |
||
516 | 'create' |
||
517 | )); |
||
518 | } |
||
519 | return $this->respondWithRedirect(moduleRoute( |
||
520 | $this->moduleName, |
||
521 | $this->routePrefix, |
||
522 | 'index', |
||
523 | ['openCreate' => true] |
||
524 | )); |
||
525 | 8 | } elseif ($input['cmsSaveType'] === 'restore') { |
|
526 | Session::flash('status', twillTrans('twill::lang.publisher.restore-success')); |
||
527 | |||
528 | return $this->respondWithRedirect(moduleRoute( |
||
529 | $this->moduleName, |
||
530 | $this->routePrefix, |
||
531 | 'edit', |
||
532 | [Str::singular($this->moduleName) => $id] |
||
533 | )); |
||
534 | } |
||
535 | } |
||
536 | |||
537 | 8 | if ($this->moduleHas('revisions')) { |
|
538 | 7 | return Response::json([ |
|
539 | 7 | 'message' => twillTrans('twill::lang.publisher.save-success'), |
|
540 | 7 | 'variant' => FlashLevel::SUCCESS, |
|
541 | 7 | 'revisions' => $item->revisionsArray(), |
|
542 | ]); |
||
543 | } |
||
544 | |||
545 | 1 | return $this->respondWithSuccess(twillTrans('twill::lang.publisher.save-success')); |
|
546 | } |
||
547 | } |
||
548 | |||
549 | /** |
||
550 | * @param int $id |
||
551 | * @return \Illuminate\View\View |
||
552 | */ |
||
553 | 1 | public function preview($id) |
|
554 | { |
||
555 | 1 | if ($this->request->has('revisionId')) { |
|
556 | $item = $this->repository->previewForRevision($id, $this->request->get('revisionId')); |
||
557 | } else { |
||
558 | 1 | $formRequest = $this->validateFormRequest(); |
|
559 | 1 | $item = $this->repository->preview($id, $formRequest->all()); |
|
560 | } |
||
561 | |||
562 | 1 | if ($this->request->has('activeLanguage')) { |
|
563 | App::setLocale($this->request->get('activeLanguage')); |
||
564 | } |
||
565 | |||
566 | 1 | $previewView = $this->previewView ?? (Config::get('twill.frontend.views_path', 'site') . '.' . Str::singular($this->moduleName)); |
|
567 | |||
568 | 1 | return View::exists($previewView) ? View::make($previewView, array_replace([ |
|
569 | 1 | 'item' => $item, |
|
570 | 1 | ], $this->previewData($item))) : View::make('twill::errors.preview', [ |
|
571 | 1 | 'moduleName' => Str::singular($this->moduleName), |
|
572 | ]); |
||
573 | } |
||
574 | |||
575 | /** |
||
576 | * @param int $id |
||
577 | * @return \Illuminate\View\View |
||
578 | */ |
||
579 | 2 | public function restoreRevision($id) |
|
580 | { |
||
581 | 2 | if ($this->request->has('revisionId')) { |
|
582 | 1 | $item = $this->repository->previewForRevision($id, $this->request->get('revisionId')); |
|
583 | 1 | $item->id = $id; |
|
584 | 1 | $item->cmsRestoring = true; |
|
585 | } else { |
||
586 | 1 | throw new NotFoundHttpException(); |
|
587 | } |
||
588 | |||
589 | 1 | $this->setBackLink(); |
|
590 | |||
591 | 1 | $view = Collection::make([ |
|
592 | 1 | "$this->viewPrefix.form", |
|
593 | 1 | "twill::$this->moduleName.form", |
|
594 | 1 | "twill::layouts.form", |
|
595 | ])->first(function ($view) { |
||
596 | 1 | return View::exists($view); |
|
597 | 1 | }); |
|
598 | |||
599 | 1 | $revision = $item->revisions()->where('id', $this->request->get('revisionId'))->first(); |
|
600 | 1 | $date = $revision->created_at->toDayDateTimeString(); |
|
601 | |||
602 | 1 | Session::flash('restoreMessage', twillTrans('twill::lang.publisher.restore-message', ['user' => $revision->byUser, 'date' => $date])); |
|
603 | |||
604 | 1 | return View::make($view, $this->form($id, $item)); |
|
605 | } |
||
606 | |||
607 | /** |
||
608 | * @return \Illuminate\Http\JsonResponse |
||
609 | */ |
||
610 | 2 | public function publish() |
|
611 | { |
||
612 | try { |
||
613 | 2 | if ($this->repository->updateBasic($this->request->get('id'), [ |
|
614 | 2 | 'published' => !$this->request->get('active'), |
|
615 | ])) { |
||
616 | 2 | activity()->performedOn( |
|
617 | 2 | $this->repository->getById($this->request->get('id')) |
|
618 | 1 | )->log( |
|
619 | 1 | ($this->request->get('active') ? 'un' : '') . 'published' |
|
620 | ); |
||
621 | |||
622 | 1 | $this->fireEvent(); |
|
623 | |||
624 | 1 | return $this->respondWithSuccess( |
|
625 | 1 | $this->modelTitle . ' ' . ($this->request->get('active') ? 'un' : '') . 'published!' |
|
626 | ); |
||
627 | } |
||
628 | 1 | } catch (\Exception $e) { |
|
629 | 1 | \Log::error($e); |
|
630 | } |
||
631 | |||
632 | 1 | return $this->respondWithError( |
|
633 | 1 | $this->modelTitle . ' was not published. Something wrong happened!' |
|
634 | ); |
||
635 | } |
||
636 | |||
637 | /** |
||
638 | * @return \Illuminate\Http\JsonResponse |
||
639 | */ |
||
640 | public function bulkPublish() |
||
641 | { |
||
642 | try { |
||
643 | if ($this->repository->updateBasic(explode(',', $this->request->get('ids')), [ |
||
644 | 'published' => $this->request->get('publish'), |
||
645 | ])) { |
||
646 | $this->fireEvent(); |
||
647 | |||
648 | return $this->respondWithSuccess( |
||
649 | $this->modelTitle . ' items ' . ($this->request->get('publish') ? '' : 'un') . 'published!' |
||
650 | ); |
||
651 | } |
||
652 | } catch (\Exception $e) { |
||
653 | \Log::error($e); |
||
654 | } |
||
655 | |||
656 | return $this->respondWithError( |
||
657 | $this->modelTitle . ' items were not published. Something wrong happened!' |
||
658 | ); |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * @param int $id |
||
663 | * @param int|null $submoduleId |
||
664 | * @return \Illuminate\Http\JsonResponse |
||
665 | */ |
||
666 | public function duplicate($id, $submoduleId = null) |
||
667 | { |
||
668 | |||
669 | $item = $this->repository->getById($submoduleId ?? $id); |
||
670 | if ($newItem = $this->repository->duplicate($submoduleId ?? $id, $this->titleColumnKey)) { |
||
671 | $this->fireEvent(); |
||
672 | activity()->performedOn($item)->log('duplicated'); |
||
673 | |||
674 | return Response::json([ |
||
675 | 'message' => $this->modelTitle . ' duplicated with Success!', |
||
676 | 'variant' => FlashLevel::SUCCESS, |
||
677 | 'redirect' => moduleRoute( |
||
678 | $this->moduleName, |
||
679 | $this->routePrefix, |
||
680 | 'edit', |
||
681 | array_filter([Str::singular($this->moduleName) => $newItem->id]) |
||
682 | ), |
||
683 | ]); |
||
684 | } |
||
685 | |||
686 | return $this->respondWithError($this->modelTitle . ' was not duplicated. Something wrong happened!'); |
||
687 | } |
||
688 | |||
689 | /** |
||
690 | * @param int $id |
||
691 | * @param int|null $submoduleId |
||
692 | * @return \Illuminate\Http\JsonResponse |
||
693 | */ |
||
694 | 2 | public function destroy($id, $submoduleId = null) |
|
695 | { |
||
696 | 2 | $item = $this->repository->getById($submoduleId ?? $id); |
|
697 | 2 | if ($this->repository->delete($submoduleId ?? $id)) { |
|
698 | 2 | $this->fireEvent(); |
|
699 | 2 | activity()->performedOn($item)->log('deleted'); |
|
700 | 2 | return $this->respondWithSuccess($this->modelTitle . ' moved to trash!'); |
|
701 | } |
||
702 | |||
703 | return $this->respondWithError($this->modelTitle . ' was not moved to trash. Something wrong happened!'); |
||
704 | } |
||
705 | |||
706 | /** |
||
707 | * @return \Illuminate\Http\JsonResponse |
||
708 | */ |
||
709 | public function bulkDelete() |
||
710 | { |
||
711 | if ($this->repository->bulkDelete(explode(',', $this->request->get('ids')))) { |
||
712 | $this->fireEvent(); |
||
713 | return $this->respondWithSuccess($this->modelTitle . ' items moved to trash!'); |
||
714 | } |
||
715 | |||
716 | return $this->respondWithError($this->modelTitle . ' items were not moved to trash. Something wrong happened!'); |
||
717 | } |
||
718 | |||
719 | /** |
||
720 | * @return \Illuminate\Http\JsonResponse |
||
721 | */ |
||
722 | public function forceDelete() |
||
723 | { |
||
724 | if ($this->repository->forceDelete($this->request->get('id'))) { |
||
725 | $this->fireEvent(); |
||
726 | return $this->respondWithSuccess($this->modelTitle . ' destroyed!'); |
||
727 | } |
||
728 | |||
729 | return $this->respondWithError($this->modelTitle . ' was not destroyed. Something wrong happened!'); |
||
730 | } |
||
731 | |||
732 | /** |
||
733 | * @return \Illuminate\Http\JsonResponse |
||
734 | */ |
||
735 | public function bulkForceDelete() |
||
736 | { |
||
737 | if ($this->repository->bulkForceDelete(explode(',', $this->request->get('ids')))) { |
||
738 | $this->fireEvent(); |
||
739 | return $this->respondWithSuccess($this->modelTitle . ' items destroyed!'); |
||
740 | } |
||
741 | |||
742 | return $this->respondWithError($this->modelTitle . ' items were not destroyed. Something wrong happened!'); |
||
743 | } |
||
744 | |||
745 | /** |
||
746 | * @return \Illuminate\Http\JsonResponse |
||
747 | */ |
||
748 | 2 | public function restore() |
|
749 | { |
||
750 | 2 | if ($this->repository->restore($this->request->get('id'))) { |
|
751 | 1 | $this->fireEvent(); |
|
752 | 1 | activity()->performedOn($this->repository->getById($this->request->get('id')))->log('restored'); |
|
753 | 1 | return $this->respondWithSuccess($this->modelTitle . ' restored!'); |
|
754 | } |
||
755 | |||
756 | 1 | return $this->respondWithError($this->modelTitle . ' was not restored. Something wrong happened!'); |
|
757 | } |
||
758 | |||
759 | /** |
||
760 | * @return \Illuminate\Http\JsonResponse |
||
761 | */ |
||
762 | public function bulkRestore() |
||
763 | { |
||
764 | if ($this->repository->bulkRestore(explode(',', $this->request->get('ids')))) { |
||
765 | $this->fireEvent(); |
||
766 | return $this->respondWithSuccess($this->modelTitle . ' items restored!'); |
||
767 | } |
||
768 | |||
769 | return $this->respondWithError($this->modelTitle . ' items were not restored. Something wrong happened!'); |
||
770 | } |
||
771 | |||
772 | /** |
||
773 | * @return \Illuminate\Http\JsonResponse |
||
774 | */ |
||
775 | 2 | public function feature() |
|
776 | { |
||
777 | 2 | if (($id = $this->request->get('id'))) { |
|
778 | 2 | $featuredField = $this->request->get('featureField') ?? $this->featureField; |
|
779 | 2 | $featured = !$this->request->get('active'); |
|
780 | |||
781 | 2 | if ($this->repository->isUniqueFeature()) { |
|
782 | if ($featured) { |
||
783 | $this->repository->updateBasic(null, [$featuredField => false]); |
||
784 | $this->repository->updateBasic($id, [$featuredField => $featured]); |
||
785 | } |
||
786 | } else { |
||
787 | 2 | $this->repository->updateBasic($id, [$featuredField => $featured]); |
|
788 | } |
||
789 | |||
790 | 2 | activity()->performedOn( |
|
791 | 2 | $this->repository->getById($id) |
|
792 | 1 | )->log( |
|
793 | 1 | ($this->request->get('active') ? 'un' : '') . 'featured' |
|
794 | ); |
||
795 | |||
796 | 1 | $this->fireEvent(); |
|
797 | 1 | return $this->respondWithSuccess($this->modelTitle . ' ' . ($this->request->get('active') ? 'un' : '') . 'featured!'); |
|
798 | } |
||
799 | |||
800 | return $this->respondWithError($this->modelTitle . ' was not featured. Something wrong happened!'); |
||
801 | } |
||
802 | |||
803 | /** |
||
804 | * @return \Illuminate\Http\JsonResponse |
||
805 | */ |
||
806 | public function bulkFeature() |
||
807 | { |
||
808 | if (($ids = explode(',', $this->request->get('ids')))) { |
||
809 | $featuredField = $this->request->get('featureField') ?? $this->featureField; |
||
810 | $featured = $this->request->get('feature') ?? true; |
||
811 | // we don't need to check if unique feature since bulk operation shouldn't be allowed in this case |
||
812 | $this->repository->updateBasic($ids, [$featuredField => $featured]); |
||
813 | $this->fireEvent(); |
||
814 | return $this->respondWithSuccess($this->modelTitle . ' items ' . ($this->request->get('feature') ? '' : 'un') . 'featured!'); |
||
815 | } |
||
816 | |||
817 | return $this->respondWithError($this->modelTitle . ' items were not featured. Something wrong happened!'); |
||
818 | } |
||
819 | |||
820 | /** |
||
821 | * @return \Illuminate\Http\JsonResponse |
||
822 | */ |
||
823 | 4 | public function reorder() |
|
824 | { |
||
825 | 4 | if (($values = $this->request->get('ids')) && !empty($values)) { |
|
826 | 4 | $this->repository->setNewOrder($values); |
|
827 | 3 | $this->fireEvent(); |
|
828 | 3 | return $this->respondWithSuccess($this->modelTitle . ' order changed!'); |
|
829 | } |
||
830 | |||
831 | return $this->respondWithError($this->modelTitle . ' order was not changed. Something wrong happened!'); |
||
832 | } |
||
833 | |||
834 | /** |
||
835 | * @return \Illuminate\Http\JsonResponse |
||
836 | */ |
||
837 | 1 | public function tags() |
|
838 | { |
||
839 | 1 | $query = $this->request->input('q'); |
|
840 | 1 | $tags = $this->repository->getTags($query); |
|
841 | |||
842 | return Response::json(['items' => $tags->map(function ($tag) { |
||
843 | return $tag->name; |
||
844 | 1 | })], 200); |
|
845 | } |
||
846 | |||
847 | /** |
||
848 | * @param array $prependScope |
||
849 | * @return array |
||
850 | */ |
||
851 | 6 | protected function getIndexData($prependScope = []) |
|
852 | { |
||
853 | 6 | $scopes = $this->filterScope($prependScope); |
|
854 | 6 | $items = $this->getIndexItems($scopes); |
|
855 | |||
856 | $data = [ |
||
857 | 6 | 'tableData' => $this->getIndexTableData($items), |
|
858 | 6 | 'tableColumns' => $this->getIndexTableColumns($items), |
|
859 | 6 | 'tableMainFilters' => $this->getIndexTableMainFilters($items), |
|
860 | 6 | 'filters' => json_decode($this->request->get('filter'), true) ?? [], |
|
861 | 6 | 'hiddenFilters' => array_keys(Arr::except($this->filters, array_keys($this->defaultFilters))), |
|
862 | 6 | 'filterLinks' => $this->filterLinks ?? [], |
|
863 | 6 | 'maxPage' => method_exists($items, 'lastPage') ? $items->lastPage() : 1, |
|
864 | 6 | 'defaultMaxPage' => method_exists($items, 'total') ? ceil($items->total() / $this->perPage) : 1, |
|
865 | 6 | 'offset' => method_exists($items, 'perPage') ? $items->perPage() : count($items), |
|
866 | 6 | 'defaultOffset' => $this->perPage, |
|
867 | 6 | ] + $this->getIndexUrls($this->moduleName, $this->routePrefix); |
|
868 | |||
869 | 6 | $baseUrl = $this->getPermalinkBaseUrl(); |
|
870 | |||
871 | $options = [ |
||
872 | 6 | 'moduleName' => $this->moduleName, |
|
873 | 6 | 'skipCreateModal' => $this->getIndexOption('skipCreateModal'), |
|
874 | 6 | 'reorder' => $this->getIndexOption('reorder'), |
|
875 | 6 | 'create' => $this->getIndexOption('create'), |
|
876 | 6 | 'duplicate' => $this->getIndexOption('duplicate'), |
|
877 | 6 | 'translate' => $this->moduleHas('translations'), |
|
878 | 6 | 'translateTitle' => $this->titleIsTranslatable(), |
|
879 | 6 | 'permalink' => $this->getIndexOption('permalink'), |
|
880 | 6 | 'bulkEdit' => $this->getIndexOption('bulkEdit'), |
|
881 | 6 | 'titleFormKey' => $this->titleFormKey ?? $this->titleColumnKey, |
|
882 | 6 | 'baseUrl' => $baseUrl, |
|
883 | 6 | 'permalinkPrefix' => $this->getPermalinkPrefix($baseUrl), |
|
884 | ]; |
||
885 | |||
886 | 6 | return array_replace_recursive($data + $options, $this->indexData($this->request)); |
|
887 | } |
||
888 | |||
889 | /** |
||
890 | * @param Request $request |
||
891 | * @return array |
||
892 | */ |
||
893 | 5 | protected function indexData($request) |
|
894 | { |
||
895 | 5 | return []; |
|
896 | } |
||
897 | |||
898 | /** |
||
899 | * @param array $scopes |
||
900 | * @param bool $forcePagination |
||
901 | * @return \Illuminate\Database\Eloquent\Collection |
||
902 | */ |
||
903 | 12 | protected function getIndexItems($scopes = [], $forcePagination = false) |
|
904 | { |
||
905 | 12 | return $this->transformIndexItems($this->repository->get( |
|
906 | 12 | $this->indexWith, |
|
907 | $scopes, |
||
908 | 12 | $this->orderScope(), |
|
909 | 12 | $this->request->get('offset') ?? $this->perPage ?? 50, |
|
910 | $forcePagination |
||
911 | )); |
||
912 | } |
||
913 | |||
914 | /** |
||
915 | * @param \Illuminate\Database\Eloquent\Collection $items |
||
916 | * @return \Illuminate\Database\Eloquent\Collection |
||
917 | */ |
||
918 | 10 | protected function transformIndexItems($items) |
|
919 | { |
||
920 | 10 | return $items; |
|
921 | } |
||
922 | |||
923 | /** |
||
924 | * @param \Illuminate\Database\Eloquent\Collection $items |
||
925 | * @return array |
||
926 | */ |
||
927 | 6 | protected function getIndexTableData($items) |
|
928 | { |
||
929 | 6 | $translated = $this->moduleHas('translations'); |
|
930 | return $items->map(function ($item) use ($translated) { |
||
931 | $columnsData = Collection::make($this->indexColumns)->mapWithKeys(function ($column) use ($item) { |
||
932 | 3 | return $this->getItemColumnData($item, $column); |
|
933 | 3 | })->toArray(); |
|
934 | |||
935 | 3 | $name = $columnsData[$this->titleColumnKey]; |
|
936 | |||
937 | 3 | if (empty($name)) { |
|
938 | if ($this->moduleHas('translations')) { |
||
939 | $fallBackTranslation = $item->translations()->where('active', true)->first(); |
||
940 | |||
941 | if (isset($fallBackTranslation->{$this->titleColumnKey})) { |
||
942 | $name = $fallBackTranslation->{$this->titleColumnKey}; |
||
943 | } |
||
944 | } |
||
945 | |||
946 | $name = $name ?? ('Missing ' . $this->titleColumnKey); |
||
947 | } |
||
948 | |||
949 | 3 | unset($columnsData[$this->titleColumnKey]); |
|
950 | |||
951 | 3 | $itemIsTrashed = method_exists($item, 'trashed') && $item->trashed(); |
|
952 | 3 | $itemCanDelete = $this->getIndexOption('delete') && ($item->canDelete ?? true); |
|
953 | 3 | $canEdit = $this->getIndexOption('edit'); |
|
954 | 3 | $canDuplicate = $this->getIndexOption('duplicate'); |
|
955 | |||
956 | 3 | return array_replace([ |
|
957 | 3 | 'id' => $item->id, |
|
958 | 3 | 'name' => $name, |
|
959 | 3 | 'publish_start_date' => $item->publish_start_date, |
|
960 | 3 | 'publish_end_date' => $item->publish_end_date, |
|
961 | 3 | 'edit' => $canEdit ? $this->getModuleRoute($item->id, 'edit') : null, |
|
962 | 3 | 'duplicate' => $canDuplicate ? $this->getModuleRoute($item->id, 'duplicate') : null, |
|
963 | 3 | 'delete' => $itemCanDelete ? $this->getModuleRoute($item->id, 'destroy') : null, |
|
964 | 3 | ] + ($this->getIndexOption('editInModal') ? [ |
|
965 | 1 | 'editInModal' => $this->getModuleRoute($item->id, 'edit'), |
|
966 | 1 | 'updateUrl' => $this->getModuleRoute($item->id, 'update'), |
|
967 | 3 | ] : []) + ($this->getIndexOption('publish') && ($item->canPublish ?? true) ? [ |
|
968 | 3 | 'published' => $item->published, |
|
969 | 3 | ] : []) + ($this->getIndexOption('feature') && ($item->canFeature ?? true) ? [ |
|
970 | 'featured' => $item->{$this->featureField}, |
||
971 | 3 | ] : []) + (($this->getIndexOption('restore') && $itemIsTrashed) ? [ |
|
972 | 'deleted' => true, |
||
973 | 3 | ] : []) + (($this->getIndexOption('forceDelete') && $itemIsTrashed) ? [ |
|
974 | 'destroyable' => true, |
||
975 | 3 | ] : []) + ($translated ? [ |
|
976 | 3 | 'languages' => $item->getActiveLanguages(), |
|
977 | 3 | ] : []) + $columnsData, $this->indexItemData($item)); |
|
978 | 6 | })->toArray(); |
|
979 | } |
||
980 | |||
981 | /** |
||
982 | * @param \A17\Twill\Models\Model $item |
||
983 | * @return array |
||
984 | */ |
||
985 | 2 | protected function indexItemData($item) |
|
986 | { |
||
987 | 2 | return []; |
|
988 | } |
||
989 | |||
990 | /** |
||
991 | * @param \A17\Twill\Models\Model $item |
||
992 | * @param array $column |
||
993 | * @return array |
||
994 | */ |
||
995 | 5 | protected function getItemColumnData($item, $column) |
|
996 | { |
||
997 | 5 | if (isset($column['thumb']) && $column['thumb']) { |
|
998 | 2 | if (isset($column['present']) && $column['present']) { |
|
999 | return [ |
||
1000 | 'thumbnail' => $item->presentAdmin()->{$column['presenter']}, |
||
1001 | ]; |
||
1002 | } else { |
||
1003 | 2 | $variant = isset($column['variant']); |
|
1004 | 2 | $role = $variant ? $column['variant']['role'] : head(array_keys($item->mediasParams)); |
|
1005 | 2 | $crop = $variant ? $column['variant']['crop'] : head(array_keys(head($item->mediasParams))); |
|
1006 | 2 | $params = $variant && isset($column['variant']['params']) |
|
1007 | ? $column['variant']['params'] |
||
1008 | 2 | : ['w' => 80, 'h' => 80, 'fit' => 'crop']; |
|
1009 | |||
1010 | return [ |
||
1011 | 2 | 'thumbnail' => $item->cmsImage($role, $crop, $params), |
|
1012 | ]; |
||
1013 | } |
||
1014 | } |
||
1015 | |||
1016 | 5 | if (isset($column['nested']) && $column['nested']) { |
|
1017 | $field = $column['nested']; |
||
1018 | $nestedCount = $item->{$column['nested']}->count(); |
||
1019 | $value = '<a href="'; |
||
1020 | $value .= moduleRoute("$this->moduleName.$field", $this->routePrefix, 'index', [$item->id]); |
||
1021 | $value .= '">' . $nestedCount . " " . (strtolower($nestedCount > 1 |
||
1022 | ? Str::plural($column['title']) |
||
1023 | : Str::singular($column['title']))) . '</a>'; |
||
1024 | } else { |
||
1025 | 5 | $field = $column['field']; |
|
1026 | 5 | $value = $item->$field; |
|
1027 | } |
||
1028 | |||
1029 | 5 | if (isset($column['relationship'])) { |
|
1030 | $field = $column['relationship'] . ucfirst($column['field']); |
||
1031 | $value = Arr::get($item, "{$column['relationship']}.{$column['field']}"); |
||
1032 | 5 | } elseif (isset($column['present']) && $column['present']) { |
|
1033 | $value = $item->presentAdmin()->{$column['field']}; |
||
1034 | } |
||
1035 | |||
1036 | return [ |
||
1037 | 5 | "$field" => $value, |
|
1038 | ]; |
||
1039 | } |
||
1040 | |||
1041 | /** |
||
1042 | * @param \Illuminate\Database\Eloquent\Collection $items |
||
1043 | * @return array |
||
1044 | */ |
||
1045 | 6 | protected function getIndexTableColumns($items) |
|
1046 | { |
||
1047 | 6 | $tableColumns = []; |
|
1048 | 6 | $visibleColumns = $this->request->get('columns') ?? false; |
|
1049 | |||
1050 | 6 | if (isset(Arr::first($this->indexColumns)['thumb']) |
|
1051 | 6 | && Arr::first($this->indexColumns)['thumb'] |
|
1052 | ) { |
||
1053 | 4 | array_push($tableColumns, [ |
|
1054 | 4 | 'name' => 'thumbnail', |
|
1055 | 4 | 'label' => twillTrans('twill::lang.listing.columns.thumbnail'), |
|
1056 | 4 | 'visible' => $visibleColumns ? in_array('thumbnail', $visibleColumns) : true, |
|
1057 | 'optional' => true, |
||
1058 | 'sortable' => false, |
||
1059 | ]); |
||
1060 | 4 | array_shift($this->indexColumns); |
|
1061 | } |
||
1062 | |||
1063 | 6 | if ($this->getIndexOption('feature')) { |
|
1064 | array_push($tableColumns, [ |
||
1065 | 'name' => 'featured', |
||
1066 | 'label' => twillTrans('twill::lang.listing.columns.featured'), |
||
1067 | 'visible' => true, |
||
1068 | 'optional' => false, |
||
1069 | 'sortable' => false, |
||
1070 | ]); |
||
1071 | } |
||
1072 | |||
1073 | 6 | if ($this->getIndexOption('publish')) { |
|
1074 | 6 | array_push($tableColumns, [ |
|
1075 | 6 | 'name' => 'published', |
|
1076 | 6 | 'label' => twillTrans('twill::lang.listing.columns.published'), |
|
1077 | 'visible' => true, |
||
1078 | 'optional' => false, |
||
1079 | 'sortable' => false, |
||
1080 | ]); |
||
1081 | } |
||
1082 | |||
1083 | 6 | array_push($tableColumns, [ |
|
1084 | 6 | 'name' => 'name', |
|
1085 | 6 | 'label' => $this->indexColumns[$this->titleColumnKey]['title'] ?? twillTrans('twill::lang.listing.columns.name'), |
|
1086 | 'visible' => true, |
||
1087 | 'optional' => false, |
||
1088 | 6 | 'sortable' => $this->getIndexOption('reorder') ? false : ($this->indexColumns[$this->titleColumnKey]['sort'] ?? false), |
|
1089 | ]); |
||
1090 | |||
1091 | 6 | unset($this->indexColumns[$this->titleColumnKey]); |
|
1092 | |||
1093 | 6 | foreach ($this->indexColumns as $column) { |
|
1094 | 4 | $columnName = isset($column['relationship']) |
|
1095 | ? $column['relationship'] . ucfirst($column['field']) |
||
1096 | 4 | : (isset($column['nested']) ? $column['nested'] : $column['field']); |
|
1097 | |||
1098 | 4 | array_push($tableColumns, [ |
|
1099 | 4 | 'name' => $columnName, |
|
1100 | 4 | 'label' => $column['title'], |
|
1101 | 4 | 'visible' => $visibleColumns ? in_array($columnName, $visibleColumns) : ($column['visible'] ?? true), |
|
1102 | 4 | 'optional' => $column['optional'] ?? true, |
|
1103 | 4 | 'sortable' => $this->getIndexOption('reorder') ? false : ($column['sort'] ?? false), |
|
1104 | 4 | 'html' => $column['html'] ?? false, |
|
1105 | ]); |
||
1106 | } |
||
1107 | |||
1108 | 6 | if ($this->moduleHas('translations')) { |
|
1109 | 5 | array_push($tableColumns, [ |
|
1110 | 5 | 'name' => 'languages', |
|
1111 | 5 | 'label' => twillTrans('twill::lang.listing.languages'), |
|
1112 | 5 | 'visible' => $visibleColumns ? in_array('languages', $visibleColumns) : true, |
|
1113 | 'optional' => true, |
||
1114 | 'sortable' => false, |
||
1115 | ]); |
||
1116 | } |
||
1117 | |||
1118 | 6 | return $tableColumns; |
|
1119 | } |
||
1120 | |||
1121 | /** |
||
1122 | * @param \Illuminate\Database\Eloquent\Collection $items |
||
1123 | * @param array $scopes |
||
1124 | * @return array |
||
1125 | */ |
||
1126 | 5 | protected function getIndexTableMainFilters($items, $scopes = []) |
|
1127 | { |
||
1128 | 5 | $statusFilters = []; |
|
1129 | |||
1130 | 5 | $scope = ($this->submodule ? [ |
|
1131 | $this->getParentModuleForeignKey() => $this->submoduleParentId, |
||
1132 | 5 | ] : []) + $scopes; |
|
1133 | |||
1134 | 5 | array_push($statusFilters, [ |
|
1135 | 5 | 'name' => twillTrans('twill::lang.listing.filter.all-items'), |
|
1136 | 5 | 'slug' => 'all', |
|
1137 | 5 | 'number' => $this->repository->getCountByStatusSlug('all', $scope), |
|
1138 | ]); |
||
1139 | |||
1140 | 5 | if ($this->moduleHas('revisions') && $this->getIndexOption('create')) { |
|
1141 | 5 | array_push($statusFilters, [ |
|
1142 | 5 | 'name' => twillTrans('twill::lang.listing.filter.mine'), |
|
1143 | 5 | 'slug' => 'mine', |
|
1144 | 5 | 'number' => $this->repository->getCountByStatusSlug('mine', $scope), |
|
1145 | ]); |
||
1146 | } |
||
1147 | |||
1148 | 5 | if ($this->getIndexOption('publish')) { |
|
1149 | 5 | array_push($statusFilters, [ |
|
1150 | 5 | 'name' => twillTrans('twill::lang.listing.filter.published'), |
|
1151 | 5 | 'slug' => 'published', |
|
1152 | 5 | 'number' => $this->repository->getCountByStatusSlug('published', $scope), |
|
1153 | ], [ |
||
1154 | 5 | 'name' => twillTrans('twill::lang.listing.filter.draft'), |
|
1155 | 5 | 'slug' => 'draft', |
|
1156 | 5 | 'number' => $this->repository->getCountByStatusSlug('draft', $scope), |
|
1157 | ]); |
||
1158 | } |
||
1159 | |||
1160 | 5 | if ($this->getIndexOption('restore')) { |
|
1161 | 5 | array_push($statusFilters, [ |
|
1162 | 5 | 'name' => twillTrans('twill::lang.listing.filter.trash'), |
|
1163 | 5 | 'slug' => 'trash', |
|
1164 | 5 | 'number' => $this->repository->getCountByStatusSlug('trash', $scope), |
|
1165 | ]); |
||
1166 | } |
||
1167 | |||
1168 | 5 | return $statusFilters; |
|
1169 | } |
||
1170 | |||
1171 | /** |
||
1172 | * @param string $moduleName |
||
1173 | * @param string $routePrefix |
||
1174 | * @return array |
||
1175 | */ |
||
1176 | 6 | protected function getIndexUrls($moduleName, $routePrefix) |
|
1177 | { |
||
1178 | 6 | return Collection::make([ |
|
1179 | 6 | 'create', |
|
1180 | 'store', |
||
1181 | 'publish', |
||
1182 | 'bulkPublish', |
||
1183 | 'restore', |
||
1184 | 'bulkRestore', |
||
1185 | 'forceDelete', |
||
1186 | 'bulkForceDelete', |
||
1187 | 'reorder', |
||
1188 | 'feature', |
||
1189 | 'bulkFeature', |
||
1190 | 'bulkDelete', |
||
1191 | ])->mapWithKeys(function ($endpoint) { |
||
1192 | return [ |
||
1193 | 6 | $endpoint . 'Url' => $this->getIndexOption($endpoint) ? moduleRoute( |
|
1194 | 6 | $this->moduleName, $this->routePrefix, $endpoint, |
|
1195 | 6 | $this->submodule ? [$this->submoduleParentId] : [] |
|
1196 | ) : null, |
||
1197 | ]; |
||
1198 | 6 | })->toArray(); |
|
1199 | } |
||
1200 | |||
1201 | /** |
||
1202 | * @param string $option |
||
1203 | * @return bool |
||
1204 | */ |
||
1205 | 33 | protected function getIndexOption($option) |
|
1206 | { |
||
1207 | return once(function () use ($option) { |
||
1208 | $customOptionNamesMapping = [ |
||
1209 | 33 | 'store' => 'create', |
|
1210 | ]; |
||
1211 | |||
1212 | 33 | $option = array_key_exists($option, $customOptionNamesMapping) ? $customOptionNamesMapping[$option] : $option; |
|
1213 | |||
1214 | $authorizableOptions = [ |
||
1215 | 33 | 'create' => 'edit', |
|
1216 | 'edit' => 'edit', |
||
1217 | 'publish' => 'publish', |
||
1218 | 'feature' => 'feature', |
||
1219 | 'reorder' => 'reorder', |
||
1220 | 'delete' => 'delete', |
||
1221 | 'duplicate' => 'duplicate', |
||
1222 | 'restore' => 'delete', |
||
1223 | 'forceDelete' => 'delete', |
||
1224 | 'bulkForceDelete' => 'delete', |
||
1225 | 'bulkPublish' => 'publish', |
||
1226 | 'bulkRestore' => 'delete', |
||
1227 | 'bulkFeature' => 'feature', |
||
1228 | 'bulkDelete' => 'delete', |
||
1229 | 'bulkEdit' => 'edit', |
||
1230 | 'editInModal' => 'edit', |
||
1231 | 'skipCreateModal' => 'edit', |
||
1232 | ]; |
||
1233 | |||
1234 | 33 | $authorized = array_key_exists($option, $authorizableOptions) ? Auth::guard('twill_users')->user()->can($authorizableOptions[$option]) : true; |
|
1235 | 33 | return ($this->indexOptions[$option] ?? $this->defaultIndexOptions[$option] ?? false) && $authorized; |
|
1236 | 33 | }); |
|
1237 | } |
||
1238 | |||
1239 | /** |
||
1240 | * @param array $prependScope |
||
1241 | * @return array |
||
1242 | */ |
||
1243 | 2 | protected function getBrowserData($prependScope = []) |
|
1244 | { |
||
1245 | 2 | if ($this->request->has('except')) { |
|
1246 | $prependScope['exceptIds'] = $this->request->get('except'); |
||
1247 | } |
||
1248 | |||
1249 | 2 | $scopes = $this->filterScope($prependScope); |
|
1250 | 2 | $items = $this->getBrowserItems($scopes); |
|
1251 | 2 | $data = $this->getBrowserTableData($items); |
|
1252 | |||
1253 | 2 | return array_replace_recursive(['data' => $data], $this->indexData($this->request)); |
|
1254 | } |
||
1255 | |||
1256 | /** |
||
1257 | * @param \Illuminate\Database\Eloquent\Collection $items |
||
1258 | * @return array |
||
1259 | */ |
||
1260 | 2 | protected function getBrowserTableData($items) |
|
1261 | { |
||
1262 | 2 | $withImage = $this->moduleHas('medias'); |
|
1263 | |||
1264 | return $items->map(function ($item) use ($withImage) { |
||
1265 | $columnsData = Collection::make($this->browserColumns)->mapWithKeys(function ($column) use ($item) { |
||
1266 | 2 | return $this->getItemColumnData($item, $column); |
|
1267 | 2 | })->toArray(); |
|
1268 | |||
1269 | 2 | $name = $columnsData[$this->titleColumnKey]; |
|
1270 | 2 | unset($columnsData[$this->titleColumnKey]); |
|
1271 | |||
1272 | return [ |
||
1273 | 2 | 'id' => $item->id, |
|
1274 | 2 | 'name' => $name, |
|
1275 | 2 | 'edit' => moduleRoute($this->moduleName, $this->routePrefix, 'edit', $item->id), |
|
1276 | 2 | 'endpointType' => $this->repository->getMorphClass(), |
|
1277 | 2 | ] + $columnsData + ($withImage && !array_key_exists('thumbnail', $columnsData) ? [ |
|
1278 | 2 | 'thumbnail' => $item->defaultCmsImage(['w' => 100, 'h' => 100]), |
|
1279 | 2 | ] : []); |
|
1280 | 2 | })->toArray(); |
|
1281 | } |
||
1282 | |||
1283 | /** |
||
1284 | * @param array $scopes |
||
1285 | * @return \Illuminate\Database\Eloquent\Collection |
||
1286 | */ |
||
1287 | 2 | protected function getBrowserItems($scopes = []) |
|
1288 | { |
||
1289 | 2 | return $this->getIndexItems($scopes, true); |
|
1290 | } |
||
1291 | |||
1292 | /** |
||
1293 | * @param array $prepend |
||
1294 | * @return array |
||
1295 | */ |
||
1296 | 12 | protected function filterScope($prepend = []) |
|
1297 | { |
||
1298 | 12 | $scope = []; |
|
1299 | |||
1300 | 12 | $requestFilters = $this->getRequestFilters(); |
|
1301 | |||
1302 | 12 | $this->filters = array_merge($this->filters, $this->defaultFilters); |
|
1303 | |||
1304 | 12 | if (array_key_exists('status', $requestFilters)) { |
|
1305 | 1 | switch ($requestFilters['status']) { |
|
1306 | 1 | case 'published': |
|
1307 | 1 | $scope['published'] = true; |
|
1308 | 1 | break; |
|
1309 | case 'draft': |
||
1310 | $scope['draft'] = true; |
||
1311 | break; |
||
1312 | case 'trash': |
||
1313 | $scope['onlyTrashed'] = true; |
||
1314 | break; |
||
1315 | case 'mine': |
||
1316 | $scope['mine'] = true; |
||
1317 | break; |
||
1318 | } |
||
1319 | |||
1320 | 1 | unset($requestFilters['status']); |
|
1321 | } |
||
1322 | |||
1323 | 12 | foreach ($this->filters as $key => $field) { |
|
1324 | 12 | if (array_key_exists($key, $requestFilters)) { |
|
1325 | 2 | $value = $requestFilters[$key]; |
|
1326 | 2 | if ($value == 0 || !empty($value)) { |
|
1327 | // add some syntaxic sugar to scope the same filter on multiple columns |
||
1328 | 2 | $fieldSplitted = explode('|', $field); |
|
1329 | 2 | if (count($fieldSplitted) > 1) { |
|
1330 | $requestValue = $requestFilters[$key]; |
||
1331 | Collection::make($fieldSplitted)->each(function ($scopeKey) use (&$scope, $requestValue) { |
||
1332 | $scope[$scopeKey] = $requestValue; |
||
1333 | }); |
||
1334 | } else { |
||
1335 | 2 | $scope[$field] = $requestFilters[$key]; |
|
1336 | } |
||
1337 | } |
||
1338 | } |
||
1339 | } |
||
1340 | |||
1341 | 12 | return $prepend + $scope; |
|
1342 | } |
||
1343 | |||
1344 | /** |
||
1345 | * @return array |
||
1346 | */ |
||
1347 | 7 | protected function getRequestFilters() |
|
1348 | { |
||
1349 | 7 | if ($this->request->has('search')) { |
|
1350 | return ['search' => $this->request->get('search')]; |
||
1351 | } |
||
1352 | |||
1353 | 7 | return json_decode($this->request->get('filter'), true) ?? []; |
|
1354 | } |
||
1355 | |||
1356 | /** |
||
1357 | * @return void |
||
1358 | */ |
||
1359 | 44 | protected function applyFiltersDefaultOptions() |
|
1360 | { |
||
1361 | 44 | if (!count($this->filtersDefaultOptions) || $this->request->has('search')) { |
|
1362 | 44 | return; |
|
1363 | } |
||
1364 | |||
1365 | $filters = $this->getRequestFilters(); |
||
1366 | |||
1367 | foreach ($this->filtersDefaultOptions as $filterName => $defaultOption) { |
||
1368 | if (!isset($filters[$filterName])) { |
||
1369 | $filters[$filterName] = $defaultOption; |
||
1370 | } |
||
1371 | } |
||
1372 | |||
1373 | $this->request->merge(['filter' => json_encode($filters)]); |
||
1374 | } |
||
1375 | |||
1376 | /** |
||
1377 | * @return array |
||
1378 | */ |
||
1379 | 12 | protected function orderScope() |
|
1380 | { |
||
1381 | 12 | $orders = []; |
|
1382 | 12 | if ($this->request->has('sortKey') && $this->request->has('sortDir')) { |
|
1383 | 1 | if (($key = $this->request->get('sortKey')) == 'name') { |
|
1384 | $sortKey = $this->titleColumnKey; |
||
1385 | 1 | } elseif (!empty($key)) { |
|
1386 | 1 | $sortKey = $key; |
|
1387 | } |
||
1388 | |||
1389 | 1 | if (isset($sortKey)) { |
|
1390 | 1 | $orders[$this->indexColumns[$sortKey]['sortKey'] ?? $sortKey] = $this->request->get('sortDir'); |
|
1391 | } |
||
1392 | } |
||
1393 | |||
1394 | // don't apply default orders if reorder is enabled |
||
1395 | 12 | $reorder = $this->getIndexOption('reorder'); |
|
1396 | 12 | $defaultOrders = ($reorder ? [] : ($this->defaultOrders ?? [])); |
|
1397 | |||
1398 | 12 | return $orders + $defaultOrders; |
|
1399 | } |
||
1400 | |||
1401 | /** |
||
1402 | * @param int $id |
||
1403 | * @param \A17\Twill\Models\Model|null $item |
||
1404 | * @return array |
||
1405 | */ |
||
1406 | 5 | protected function form($id, $item = null) |
|
1407 | { |
||
1408 | |||
1409 | 5 | if (!$item && $id) { |
|
1410 | 4 | $item = $this->repository->getById($id, $this->formWith, $this->formWithCount); |
|
1411 | 1 | } elseif (!$item && !$id) { |
|
1412 | $item = $this->repository->newInstance(); |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
1413 | } |
||
1414 | |||
1415 | 5 | $fullRoutePrefix = 'admin.' . ($this->routePrefix ? $this->routePrefix . '.' : '') . $this->moduleName . '.'; |
|
1416 | 5 | $previewRouteName = $fullRoutePrefix . 'preview'; |
|
1417 | 5 | $restoreRouteName = $fullRoutePrefix . 'restoreRevision'; |
|
1418 | |||
1419 | 5 | $baseUrl = $item->urlWithoutSlug ?? $this->getPermalinkBaseUrl(); |
|
1420 | |||
1421 | $data = [ |
||
1422 | 5 | 'item' => $item, |
|
1423 | 5 | 'moduleName' => $this->moduleName, |
|
1424 | 5 | 'routePrefix' => $this->routePrefix, |
|
1425 | 5 | 'titleFormKey' => $this->titleFormKey ?? $this->titleColumnKey, |
|
1426 | 5 | 'publish' => $item->canPublish ?? true, |
|
1427 | 5 | 'publishDate24Hr' => Config::get('twill.publish_date_24h') ?? false, |
|
1428 | 5 | 'publishDateFormat' => Config::get('twill.publish_date_format') ?? null, |
|
1429 | 5 | 'publishDateDisplayFormat' => Config::get('twill.publish_date_display_format') ?? null, |
|
1430 | 5 | 'translate' => $this->moduleHas('translations'), |
|
1431 | 5 | 'translateTitle' => $this->titleIsTranslatable(), |
|
1432 | 5 | 'permalink' => $this->getIndexOption('permalink'), |
|
1433 | 5 | 'createWithoutModal' => !$item->id && $this->getIndexOption('skipCreateModal'), |
|
1434 | 5 | 'form_fields' => $this->repository->getFormFields($item), |
|
1435 | 5 | 'baseUrl' => $baseUrl, |
|
1436 | 5 | 'permalinkPrefix' => $this->getPermalinkPrefix($baseUrl), |
|
1437 | 5 | 'saveUrl' => $item->id ? $this->getModuleRoute($item->id, 'update') : moduleRoute($this->moduleName, $this->routePrefix, 'store'), |
|
1438 | 5 | 'editor' => Config::get('twill.enabled.block-editor') && $this->moduleHas('blocks') && !$this->disableEditor, |
|
1439 | 5 | 'blockPreviewUrl' => Route::has('admin.blocks.preview') ? URL::route('admin.blocks.preview') : '#', |
|
1440 | 5 | 'availableRepeaters' => $this->getRepeaterList()->toJson(), |
|
1441 | 5 | 'revisions' => $this->moduleHas('revisions') ? $item->revisionsArray() : null, |
|
1442 | 5 | ] + (Route::has($previewRouteName) && $item->id ? [ |
|
1443 | 5 | 'previewUrl' => moduleRoute($this->moduleName, $this->routePrefix, 'preview', $item->id), |
|
1444 | 5 | ] : []) |
|
1445 | 5 | + (Route::has($restoreRouteName) && $item->id ? [ |
|
1446 | 5 | 'restoreUrl' => moduleRoute($this->moduleName, $this->routePrefix, 'restoreRevision', $item->id), |
|
1447 | 5 | ] : []); |
|
1448 | |||
1449 | 5 | return array_replace_recursive($data, $this->formData($this->request)); |
|
1450 | } |
||
1451 | |||
1452 | /** |
||
1453 | * @param int $id |
||
1454 | * @return array |
||
1455 | */ |
||
1456 | 1 | protected function modalFormData($id) |
|
1457 | { |
||
1458 | 1 | $item = $this->repository->getById($id, $this->formWith, $this->formWithCount); |
|
1459 | 1 | $fields = $this->repository->getFormFields($item); |
|
1460 | 1 | $data = []; |
|
1461 | |||
1462 | 1 | if ($this->moduleHas('translations') && isset($fields['translations'])) { |
|
1463 | 1 | foreach ($fields['translations'] as $fieldName => $fieldValue) { |
|
1464 | 1 | $data['fields'][] = [ |
|
1465 | 1 | 'name' => $fieldName, |
|
1466 | 1 | 'value' => $fieldValue, |
|
1467 | ]; |
||
1468 | } |
||
1469 | |||
1470 | 1 | $data['languages'] = $item->getActiveLanguages(); |
|
1471 | |||
1472 | 1 | unset($fields['translations']); |
|
1473 | } |
||
1474 | |||
1475 | 1 | foreach ($fields as $fieldName => $fieldValue) { |
|
1476 | 1 | $data['fields'][] = [ |
|
1477 | 1 | 'name' => $fieldName, |
|
1478 | 1 | 'value' => $fieldValue, |
|
1479 | ]; |
||
1480 | } |
||
1481 | |||
1482 | 1 | return array_replace_recursive($data, $this->formData($this->request)); |
|
1483 | } |
||
1484 | |||
1485 | /** |
||
1486 | * @param Request $request |
||
1487 | * @return array |
||
1488 | */ |
||
1489 | 5 | protected function formData($request) |
|
1490 | { |
||
1491 | 5 | return []; |
|
1492 | } |
||
1493 | |||
1494 | /** |
||
1495 | * @param Request $item |
||
1496 | * @return array |
||
1497 | */ |
||
1498 | 1 | protected function previewData($item) |
|
1499 | { |
||
1500 | 1 | return []; |
|
1501 | } |
||
1502 | |||
1503 | /** |
||
1504 | * @return \A17\Twill\Http\Requests\Admin\Request |
||
1505 | */ |
||
1506 | 25 | protected function validateFormRequest() |
|
1507 | { |
||
1508 | $unauthorizedFields = Collection::make($this->fieldsPermissions)->filter(function ($permission, $field) { |
||
1509 | 4 | return Auth::guard('twill_users')->user()->cannot($permission); |
|
1510 | 25 | })->keys(); |
|
1511 | |||
1512 | $unauthorizedFields->each(function ($field) { |
||
1513 | $this->request->offsetUnset($field); |
||
1514 | 25 | }); |
|
1515 | |||
1516 | 25 | return App::make("$this->namespace\Http\Requests\Admin\\" . $this->modelName . "Request"); |
|
1517 | } |
||
1518 | |||
1519 | /** |
||
1520 | * @return string |
||
1521 | */ |
||
1522 | 44 | protected function getNamespace() |
|
1523 | { |
||
1524 | 44 | return $this->namespace ?? Config::get('twill.namespace'); |
|
1525 | } |
||
1526 | |||
1527 | /** |
||
1528 | * @return string |
||
1529 | */ |
||
1530 | 44 | protected function getRoutePrefix() |
|
1531 | { |
||
1532 | 44 | if ($this->request->route() != null) { |
|
1533 | 43 | $routePrefix = ltrim(str_replace(Config::get('twill.admin_app_path'), '', $this->request->route()->getPrefix()), "/"); |
|
1534 | 43 | return str_replace("/", ".", $routePrefix); |
|
1535 | } |
||
1536 | |||
1537 | 1 | return ''; |
|
1538 | } |
||
1539 | |||
1540 | /** |
||
1541 | * @return string |
||
1542 | */ |
||
1543 | 44 | protected function getModelName() |
|
1544 | { |
||
1545 | 44 | return $this->modelName ?? ucfirst(Str::singular($this->moduleName)); |
|
1546 | } |
||
1547 | |||
1548 | /** |
||
1549 | * @return \A17\Twill\Repositories\ModuleRepository |
||
1550 | */ |
||
1551 | 44 | protected function getRepository() |
|
1552 | { |
||
1553 | 44 | return App::make("$this->namespace\Repositories\\" . $this->modelName . "Repository"); |
|
1554 | } |
||
1555 | |||
1556 | /** |
||
1557 | * @return string |
||
1558 | */ |
||
1559 | 44 | protected function getViewPrefix() |
|
1560 | { |
||
1561 | 44 | return "admin.$this->moduleName"; |
|
1562 | } |
||
1563 | |||
1564 | /** |
||
1565 | * @return string |
||
1566 | */ |
||
1567 | 44 | protected function getModelTitle() |
|
1568 | { |
||
1569 | 44 | return camelCaseToWords($this->modelName); |
|
1570 | } |
||
1571 | |||
1572 | /** |
||
1573 | * @return string |
||
1574 | */ |
||
1575 | protected function getParentModuleForeignKey() |
||
1576 | { |
||
1577 | return Str::singular(explode('.', $this->moduleName)[0]) . '_id'; |
||
1578 | } |
||
1579 | |||
1580 | /** |
||
1581 | * @return string |
||
1582 | */ |
||
1583 | 11 | protected function getPermalinkBaseUrl() |
|
1584 | { |
||
1585 | 11 | $appUrl = Config::get('app.url'); |
|
1586 | |||
1587 | 11 | if (blank(parse_url($appUrl)['scheme'] ?? null)) { |
|
1588 | $appUrl = $this->request->getScheme() . '://' . $appUrl; |
||
1589 | } |
||
1590 | |||
1591 | 11 | return $appUrl . '/' |
|
1592 | 11 | . ($this->moduleHas('translations') ? '{language}/' : '') |
|
1593 | 11 | . ($this->moduleHas('revisions') ? '{preview}/' : '') |
|
1594 | 11 | . ($this->permalinkBase ?? $this->moduleName) |
|
1595 | 11 | . (isset($this->permalinkBase) && empty($this->permalinkBase) ? '' : '/'); |
|
1596 | } |
||
1597 | |||
1598 | /** |
||
1599 | * @param string $baseUrl |
||
1600 | * @return string |
||
1601 | */ |
||
1602 | 11 | protected function getPermalinkPrefix($baseUrl) |
|
1603 | { |
||
1604 | 11 | return rtrim(str_replace(['http://', 'https://', '{preview}/', '{language}/'], '', $baseUrl), "/") . '/'; |
|
1605 | } |
||
1606 | |||
1607 | /** |
||
1608 | * @param int $id |
||
1609 | * @param string $action |
||
1610 | * @return string |
||
1611 | */ |
||
1612 | 8 | protected function getModuleRoute($id, $action) |
|
1613 | { |
||
1614 | 8 | return moduleRoute( |
|
1615 | 8 | $this->moduleName, |
|
1616 | 8 | $this->routePrefix, |
|
1617 | $action, |
||
1618 | 8 | array_merge($this->submodule ? [$this->submoduleParentId] : [], [$id]) |
|
1619 | ); |
||
1620 | } |
||
1621 | |||
1622 | /** |
||
1623 | * @param string $behavior |
||
1624 | * @return bool |
||
1625 | */ |
||
1626 | 33 | protected function moduleHas($behavior) |
|
1627 | { |
||
1628 | 33 | return $this->repository->hasBehavior($behavior); |
|
1629 | } |
||
1630 | |||
1631 | /** |
||
1632 | * @return bool |
||
1633 | */ |
||
1634 | 11 | protected function titleIsTranslatable() |
|
1635 | { |
||
1636 | 11 | return $this->repository->isTranslatable( |
|
1637 | 11 | $this->titleColumnKey |
|
1638 | ); |
||
1639 | } |
||
1640 | |||
1641 | /** |
||
1642 | * @param string|null $back_link |
||
1643 | * @param array $params |
||
1644 | * @return void |
||
1645 | */ |
||
1646 | 5 | protected function setBackLink($back_link = null, $params = []) |
|
1647 | { |
||
1648 | 5 | if (!isset($back_link)) { |
|
1649 | 5 | if (($back_link = Session::get($this->getBackLinkSessionKey())) == null) { |
|
1650 | 5 | $back_link = $this->request->headers->get('referer') ?? moduleRoute( |
|
1651 | 5 | $this->moduleName, |
|
1652 | 5 | $this->routePrefix, |
|
1653 | 5 | 'index', |
|
1654 | $params |
||
1655 | ); |
||
1656 | } |
||
1657 | } |
||
1658 | |||
1659 | 5 | if (!Session::get($this->moduleName . '_retain')) { |
|
1660 | 1 | Session::put($this->getBackLinkSessionKey(), $back_link); |
|
1661 | } else { |
||
1662 | 4 | Session::put($this->moduleName . '_retain', false); |
|
1663 | } |
||
1664 | 5 | } |
|
1665 | |||
1666 | /** |
||
1667 | * @param string|null $fallback |
||
1668 | * @param array $params |
||
1669 | * @return string |
||
1670 | */ |
||
1671 | protected function getBackLink($fallback = null, $params = []) |
||
1672 | { |
||
1673 | $back_link = Session::get($this->getBackLinkSessionKey(), $fallback); |
||
1674 | return $back_link ?? moduleRoute($this->moduleName, $this->routePrefix, 'index', $params); |
||
1675 | } |
||
1676 | |||
1677 | /** |
||
1678 | * @return string |
||
1679 | */ |
||
1680 | 5 | protected function getBackLinkSessionKey() |
|
1681 | { |
||
1682 | 5 | return $this->moduleName . ($this->submodule ? $this->submoduleParentId ?? '' : '') . '_back_link'; |
|
1683 | } |
||
1684 | |||
1685 | /** |
||
1686 | * @param int $id |
||
1687 | * @param array $params |
||
1688 | * @return \Illuminate\Http\RedirectResponse |
||
1689 | */ |
||
1690 | 1 | protected function redirectToForm($id, $params = []) |
|
1691 | { |
||
1692 | 1 | Session::put($this->moduleName . '_retain', true); |
|
1693 | |||
1694 | 1 | return Redirect::to(moduleRoute( |
|
1695 | 1 | $this->moduleName, |
|
1696 | 1 | $this->routePrefix, |
|
1697 | 1 | 'edit', |
|
1698 | 1 | array_filter($params) + [Str::singular($this->moduleName) => $id] |
|
1699 | )); |
||
1700 | } |
||
1701 | |||
1702 | /** |
||
1703 | * @param string $message |
||
1704 | * @return \Illuminate\Http\JsonResponse |
||
1705 | */ |
||
1706 | 11 | protected function respondWithSuccess($message) |
|
1707 | { |
||
1708 | 11 | return $this->respondWithJson($message, FlashLevel::SUCCESS); |
|
1709 | } |
||
1710 | |||
1711 | /** |
||
1712 | * @param string $redirectUrl |
||
1713 | * @return \Illuminate\Http\JsonResponse |
||
1714 | */ |
||
1715 | 22 | protected function respondWithRedirect($redirectUrl) |
|
1716 | { |
||
1717 | 22 | return Response::json([ |
|
1718 | 22 | 'redirect' => $redirectUrl, |
|
1719 | ]); |
||
1720 | } |
||
1721 | |||
1722 | /** |
||
1723 | * @param string $message |
||
1724 | * @return \Illuminate\Http\JsonResponse |
||
1725 | */ |
||
1726 | 2 | protected function respondWithError($message) |
|
1727 | { |
||
1728 | 2 | return $this->respondWithJson($message, FlashLevel::ERROR); |
|
1729 | } |
||
1730 | |||
1731 | /** |
||
1732 | * @param string $message |
||
1733 | * @param mixed $variant |
||
1734 | * @return \Illuminate\Http\JsonResponse |
||
1735 | */ |
||
1736 | 13 | protected function respondWithJson($message, $variant) |
|
1737 | { |
||
1738 | 13 | return Response::json([ |
|
1739 | 13 | 'message' => $message, |
|
1740 | 13 | 'variant' => $variant, |
|
1741 | ]); |
||
1742 | } |
||
1743 | |||
1744 | /** |
||
1745 | * @param array $input |
||
1746 | * @return void |
||
1747 | */ |
||
1748 | 25 | protected function fireEvent($input = []) |
|
1749 | { |
||
1750 | 25 | fireCmsEvent('cms-module.saved', $input); |
|
1751 | 25 | } |
|
1752 | |||
1753 | /** |
||
1754 | * @return Collection |
||
1755 | */ |
||
1756 | 5 | public function getRepeaterList() |
|
1757 | { |
||
1758 | return app(BlockCollection::class)->getRepeaterList()->mapWithKeys(function ($repeater) { |
||
1759 | 5 | return [$repeater['name'] => $repeater]; |
|
1760 | 5 | }); |
|
1761 | } |
||
1762 | } |
||
1763 |