Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
908 lines (739 sloc)
31.7 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace TCG\Voyager\Http\Controllers; | |
use Exception; | |
use Illuminate\Database\Eloquent\SoftDeletes; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Auth; | |
use Illuminate\Support\Facades\DB; | |
use TCG\Voyager\Database\Schema\SchemaManager; | |
use TCG\Voyager\Events\BreadDataAdded; | |
use TCG\Voyager\Events\BreadDataDeleted; | |
use TCG\Voyager\Events\BreadDataRestored; | |
use TCG\Voyager\Events\BreadDataUpdated; | |
use TCG\Voyager\Events\BreadImagesDeleted; | |
use TCG\Voyager\Facades\Voyager; | |
use TCG\Voyager\Http\Controllers\Traits\BreadRelationshipParser; | |
class VoyagerBaseController extends Controller | |
{ | |
use BreadRelationshipParser; | |
//*************************************** | |
// ____ | |
// | _ \ | |
// | |_) | | |
// | _ < | |
// | |_) | | |
// |____/ | |
// | |
// Browse our Data Type (B)READ | |
// | |
//**************************************** | |
public function index(Request $request) | |
{ | |
// GET THE SLUG, ex. 'posts', 'pages', etc. | |
$slug = $this->getSlug($request); | |
// GET THE DataType based on the slug | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Check permission | |
$this->authorize('browse', app($dataType->model_name)); | |
$getter = $dataType->server_side ? 'paginate' : 'get'; | |
$search = (object) ['value' => $request->get('s'), 'key' => $request->get('key'), 'filter' => $request->get('filter')]; | |
$searchNames = []; | |
if ($dataType->server_side) { | |
$searchable = SchemaManager::describeTable(app($dataType->model_name)->getTable())->pluck('name')->toArray(); | |
$dataRow = Voyager::model('DataRow')->whereDataTypeId($dataType->id)->get(); | |
foreach ($searchable as $key => $value) { | |
$displayName = $dataRow->where('field', $value)->first()->getTranslatedAttribute('display_name'); | |
$searchNames[$value] = $displayName ?: ucwords(str_replace('_', ' ', $value)); | |
} | |
} | |
$orderBy = $request->get('order_by', $dataType->order_column); | |
$sortOrder = $request->get('sort_order', $dataType->order_direction); | |
$usesSoftDeletes = false; | |
$showSoftDeleted = false; | |
// Next Get or Paginate the actual content from the MODEL that corresponds to the slug DataType | |
if (strlen($dataType->model_name) != 0) { | |
$model = app($dataType->model_name); | |
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { | |
$query = $model->{$dataType->scope}(); | |
} else { | |
$query = $model::select('*'); | |
} | |
// Use withTrashed() if model uses SoftDeletes and if toggle is selected | |
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model)) && Auth::user()->can('delete', app($dataType->model_name))) { | |
$usesSoftDeletes = true; | |
if ($request->get('showSoftDeleted')) { | |
$showSoftDeleted = true; | |
$query = $query->withTrashed(); | |
} | |
} | |
// If a column has a relationship associated with it, we do not want to show that field | |
$this->removeRelationshipField($dataType, 'browse'); | |
if ($search->value != '' && $search->key && $search->filter) { | |
$search_filter = ($search->filter == 'equals') ? '=' : 'LIKE'; | |
$search_value = ($search->filter == 'equals') ? $search->value : '%'.$search->value.'%'; | |
$query->where($search->key, $search_filter, $search_value); | |
} | |
if ($orderBy && in_array($orderBy, $dataType->fields())) { | |
$querySortOrder = (!empty($sortOrder)) ? $sortOrder : 'desc'; | |
$dataTypeContent = call_user_func([ | |
$query->orderBy($orderBy, $querySortOrder), | |
$getter, | |
]); | |
} elseif ($model->timestamps) { | |
$dataTypeContent = call_user_func([$query->latest($model::CREATED_AT), $getter]); | |
} else { | |
$dataTypeContent = call_user_func([$query->orderBy($model->getKeyName(), 'DESC'), $getter]); | |
} | |
// Replace relationships' keys for labels and create READ links if a slug is provided. | |
$dataTypeContent = $this->resolveRelations($dataTypeContent, $dataType); | |
} else { | |
// If Model doesn't exist, get data from table name | |
$dataTypeContent = call_user_func([DB::table($dataType->name), $getter]); | |
$model = false; | |
} | |
// Check if BREAD is Translatable | |
$isModelTranslatable = is_bread_translatable($model); | |
// Eagerload Relations | |
$this->eagerLoadRelations($dataTypeContent, $dataType, 'browse', $isModelTranslatable); | |
// Check if server side pagination is enabled | |
$isServerSide = isset($dataType->server_side) && $dataType->server_side; | |
// Check if a default search key is set | |
$defaultSearchKey = $dataType->default_search_key ?? null; | |
// Actions | |
$actions = []; | |
if (!empty($dataTypeContent->first())) { | |
foreach (Voyager::actions() as $action) { | |
$action = new $action($dataType, $dataTypeContent->first()); | |
if ($action->shouldActionDisplayOnDataType()) { | |
$actions[] = $action; | |
} | |
} | |
} | |
// Define showCheckboxColumn | |
$showCheckboxColumn = false; | |
if (Auth::user()->can('delete', app($dataType->model_name))) { | |
$showCheckboxColumn = true; | |
} else { | |
foreach ($actions as $action) { | |
if (method_exists($action, 'massAction')) { | |
$showCheckboxColumn = true; | |
} | |
} | |
} | |
// Define orderColumn | |
$orderColumn = []; | |
if ($orderBy) { | |
$index = $dataType->browseRows->where('field', $orderBy)->keys()->first() + ($showCheckboxColumn ? 1 : 0); | |
$orderColumn = [[$index, $sortOrder ?? 'desc']]; | |
} | |
$view = 'voyager::bread.browse'; | |
if (view()->exists("voyager::$slug.browse")) { | |
$view = "voyager::$slug.browse"; | |
} | |
return Voyager::view($view, compact( | |
'actions', | |
'dataType', | |
'dataTypeContent', | |
'isModelTranslatable', | |
'search', | |
'orderBy', | |
'orderColumn', | |
'sortOrder', | |
'searchNames', | |
'isServerSide', | |
'defaultSearchKey', | |
'usesSoftDeletes', | |
'showSoftDeleted', | |
'showCheckboxColumn' | |
)); | |
} | |
//*************************************** | |
// _____ | |
// | __ \ | |
// | |__) | | |
// | _ / | |
// | | \ \ | |
// |_| \_\ | |
// | |
// Read an item of our Data Type B(R)EAD | |
// | |
//**************************************** | |
public function show(Request $request, $id) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
$isSoftDeleted = false; | |
if (strlen($dataType->model_name) != 0) { | |
$model = app($dataType->model_name); | |
// Use withTrashed() if model uses SoftDeletes and if toggle is selected | |
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { | |
$model = $model->withTrashed(); | |
} | |
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { | |
$model = $model->{$dataType->scope}(); | |
} | |
$dataTypeContent = call_user_func([$model, 'findOrFail'], $id); | |
if ($dataTypeContent->deleted_at) { | |
$isSoftDeleted = true; | |
} | |
} else { | |
// If Model doest exist, get data from table name | |
$dataTypeContent = DB::table($dataType->name)->where('id', $id)->first(); | |
} | |
// Replace relationships' keys for labels and create READ links if a slug is provided. | |
$dataTypeContent = $this->resolveRelations($dataTypeContent, $dataType, true); | |
// If a column has a relationship associated with it, we do not want to show that field | |
$this->removeRelationshipField($dataType, 'read'); | |
// Check permission | |
$this->authorize('read', $dataTypeContent); | |
// Check if BREAD is Translatable | |
$isModelTranslatable = is_bread_translatable($dataTypeContent); | |
// Eagerload Relations | |
$this->eagerLoadRelations($dataTypeContent, $dataType, 'read', $isModelTranslatable); | |
$view = 'voyager::bread.read'; | |
if (view()->exists("voyager::$slug.read")) { | |
$view = "voyager::$slug.read"; | |
} | |
return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable', 'isSoftDeleted')); | |
} | |
//*************************************** | |
// ______ | |
// | ____| | |
// | |__ | |
// | __| | |
// | |____ | |
// |______| | |
// | |
// Edit an item of our Data Type BR(E)AD | |
// | |
//**************************************** | |
public function edit(Request $request, $id) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
if (strlen($dataType->model_name) != 0) { | |
$model = app($dataType->model_name); | |
// Use withTrashed() if model uses SoftDeletes and if toggle is selected | |
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { | |
$model = $model->withTrashed(); | |
} | |
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { | |
$model = $model->{$dataType->scope}(); | |
} | |
$dataTypeContent = call_user_func([$model, 'findOrFail'], $id); | |
} else { | |
// If Model doest exist, get data from table name | |
$dataTypeContent = DB::table($dataType->name)->where('id', $id)->first(); | |
} | |
foreach ($dataType->editRows as $key => $row) { | |
$dataType->editRows[$key]['col_width'] = isset($row->details->width) ? $row->details->width : 100; | |
} | |
// If a column has a relationship associated with it, we do not want to show that field | |
$this->removeRelationshipField($dataType, 'edit'); | |
// Check permission | |
$this->authorize('edit', $dataTypeContent); | |
// Check if BREAD is Translatable | |
$isModelTranslatable = is_bread_translatable($dataTypeContent); | |
// Eagerload Relations | |
$this->eagerLoadRelations($dataTypeContent, $dataType, 'edit', $isModelTranslatable); | |
$view = 'voyager::bread.edit-add'; | |
if (view()->exists("voyager::$slug.edit-add")) { | |
$view = "voyager::$slug.edit-add"; | |
} | |
return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable')); | |
} | |
// POST BR(E)AD | |
public function update(Request $request, $id) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Compatibility with Model binding. | |
$id = $id instanceof \Illuminate\Database\Eloquent\Model ? $id->{$id->getKeyName()} : $id; | |
$model = app($dataType->model_name); | |
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { | |
$model = $model->{$dataType->scope}(); | |
} | |
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { | |
$data = $model->withTrashed()->findOrFail($id); | |
} else { | |
$data = call_user_func([$dataType->model_name, 'findOrFail'], $id); | |
} | |
// Check permission | |
$this->authorize('edit', $data); | |
// Validate fields with ajax | |
$val = $this->validateBread($request->all(), $dataType->editRows, $dataType->name, $id)->validate(); | |
$this->insertUpdateData($request, $slug, $dataType->editRows, $data); | |
event(new BreadDataUpdated($dataType, $data)); | |
if (auth()->user()->can('browse', $model)) { | |
$redirect = redirect()->route("voyager.{$dataType->slug}.index"); | |
} else { | |
$redirect = redirect()->back(); | |
} | |
return $redirect->with([ | |
'message' => __('voyager::generic.successfully_updated')." {$dataType->getTranslatedAttribute('display_name_singular')}", | |
'alert-type' => 'success', | |
]); | |
} | |
//*************************************** | |
// | |
// /\ | |
// / \ | |
// / /\ \ | |
// / ____ \ | |
// /_/ \_\ | |
// | |
// | |
// Add a new item of our Data Type BRE(A)D | |
// | |
//**************************************** | |
public function create(Request $request) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Check permission | |
$this->authorize('add', app($dataType->model_name)); | |
$dataTypeContent = (strlen($dataType->model_name) != 0) | |
? new $dataType->model_name() | |
: false; | |
foreach ($dataType->addRows as $key => $row) { | |
$dataType->addRows[$key]['col_width'] = $row->details->width ?? 100; | |
} | |
// If a column has a relationship associated with it, we do not want to show that field | |
$this->removeRelationshipField($dataType, 'add'); | |
// Check if BREAD is Translatable | |
$isModelTranslatable = is_bread_translatable($dataTypeContent); | |
// Eagerload Relations | |
$this->eagerLoadRelations($dataTypeContent, $dataType, 'add', $isModelTranslatable); | |
$view = 'voyager::bread.edit-add'; | |
if (view()->exists("voyager::$slug.edit-add")) { | |
$view = "voyager::$slug.edit-add"; | |
} | |
return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable')); | |
} | |
/** | |
* POST BRE(A)D - Store data. | |
* | |
* @param \Illuminate\Http\Request $request | |
* | |
* @return \Illuminate\Http\RedirectResponse | |
*/ | |
public function store(Request $request) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Check permission | |
$this->authorize('add', app($dataType->model_name)); | |
// Validate fields with ajax | |
$val = $this->validateBread($request->all(), $dataType->addRows)->validate(); | |
$data = $this->insertUpdateData($request, $slug, $dataType->addRows, new $dataType->model_name()); | |
event(new BreadDataAdded($dataType, $data)); | |
if (!$request->has('_tagging')) { | |
if (auth()->user()->can('browse', $data)) { | |
$redirect = redirect()->route("voyager.{$dataType->slug}.index"); | |
} else { | |
$redirect = redirect()->back(); | |
} | |
return $redirect->with([ | |
'message' => __('voyager::generic.successfully_added_new')." {$dataType->getTranslatedAttribute('display_name_singular')}", | |
'alert-type' => 'success', | |
]); | |
} else { | |
return response()->json(['success' => true, 'data' => $data]); | |
} | |
} | |
//*************************************** | |
// _____ | |
// | __ \ | |
// | | | | | |
// | | | | | |
// | |__| | | |
// |_____/ | |
// | |
// Delete an item BREA(D) | |
// | |
//**************************************** | |
public function destroy(Request $request, $id) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Init array of IDs | |
$ids = []; | |
if (empty($id)) { | |
// Bulk delete, get IDs from POST | |
$ids = explode(',', $request->ids); | |
} else { | |
// Single item delete, get ID from URL | |
$ids[] = $id; | |
} | |
foreach ($ids as $id) { | |
$data = call_user_func([$dataType->model_name, 'findOrFail'], $id); | |
// Check permission | |
$this->authorize('delete', $data); | |
$model = app($dataType->model_name); | |
if (!($model && in_array(SoftDeletes::class, class_uses_recursive($model)))) { | |
$this->cleanup($dataType, $data); | |
} | |
} | |
$displayName = count($ids) > 1 ? $dataType->getTranslatedAttribute('display_name_plural') : $dataType->getTranslatedAttribute('display_name_singular'); | |
$res = $data->destroy($ids); | |
$data = $res | |
? [ | |
'message' => __('voyager::generic.successfully_deleted')." {$displayName}", | |
'alert-type' => 'success', | |
] | |
: [ | |
'message' => __('voyager::generic.error_deleting')." {$displayName}", | |
'alert-type' => 'error', | |
]; | |
if ($res) { | |
event(new BreadDataDeleted($dataType, $data)); | |
} | |
return redirect()->route("voyager.{$dataType->slug}.index")->with($data); | |
} | |
public function restore(Request $request, $id) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Check permission | |
$this->authorize('delete', app($dataType->model_name)); | |
// Get record | |
$model = call_user_func([$dataType->model_name, 'withTrashed']); | |
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) { | |
$model = $model->{$dataType->scope}(); | |
} | |
$data = $model->findOrFail($id); | |
$displayName = $dataType->getTranslatedAttribute('display_name_singular'); | |
$res = $data->restore($id); | |
$data = $res | |
? [ | |
'message' => __('voyager::generic.successfully_restored')." {$displayName}", | |
'alert-type' => 'success', | |
] | |
: [ | |
'message' => __('voyager::generic.error_restoring')." {$displayName}", | |
'alert-type' => 'error', | |
]; | |
if ($res) { | |
event(new BreadDataRestored($dataType, $data)); | |
} | |
return redirect()->route("voyager.{$dataType->slug}.index")->with($data); | |
} | |
//*************************************** | |
// | |
// Delete uploaded file | |
// | |
//**************************************** | |
public function remove_media(Request $request) | |
{ | |
try { | |
// GET THE SLUG, ex. 'posts', 'pages', etc. | |
$slug = $request->get('slug'); | |
// GET file name | |
$filename = $request->get('filename'); | |
// GET record id | |
$id = $request->get('id'); | |
// GET field name | |
$field = $request->get('field'); | |
// GET multi value | |
$multi = $request->get('multi'); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Load model and find record | |
$model = app($dataType->model_name); | |
$data = $model::find([$id])->first(); | |
// Check if field exists | |
if (!isset($data->{$field})) { | |
throw new Exception(__('voyager::generic.field_does_not_exist'), 400); | |
} | |
// Check permission | |
$this->authorize('edit', $data); | |
if (@json_decode($multi)) { | |
// Check if valid json | |
if (is_null(@json_decode($data->{$field}))) { | |
throw new Exception(__('voyager::json.invalid'), 500); | |
} | |
// Decode field value | |
$fieldData = @json_decode($data->{$field}, true); | |
$key = null; | |
// Check if we're dealing with a nested array for the case of multiple files | |
if (is_array($fieldData[0])) { | |
foreach ($fieldData as $index=>$file) { | |
// file type has a different structure than images | |
if (!empty($file['original_name'])) { | |
if ($file['original_name'] == $filename) { | |
$key = $index; | |
break; | |
} | |
} else { | |
$file = array_flip($file); | |
if (array_key_exists($filename, $file)) { | |
$key = $index; | |
break; | |
} | |
} | |
} | |
} else { | |
$key = array_search($filename, $fieldData); | |
} | |
// Check if file was found in array | |
if (is_null($key) || $key === false) { | |
throw new Exception(__('voyager::media.file_does_not_exist'), 400); | |
} | |
$fileToRemove = $fieldData[$key]['download_link'] ?? $fieldData[$key]; | |
// Remove file from array | |
unset($fieldData[$key]); | |
// Generate json and update field | |
$data->{$field} = empty($fieldData) ? null : json_encode(array_values($fieldData)); | |
} else { | |
if ($filename == $data->{$field}) { | |
$fileToRemove = $data->{$field}; | |
$data->{$field} = null; | |
} else { | |
throw new Exception(__('voyager::media.file_does_not_exist'), 400); | |
} | |
} | |
$row = $dataType->rows->where('field', $field)->first(); | |
// Remove file from filesystem | |
if (in_array($row->type, ['image', 'multiple_images'])) { | |
$this->deleteBreadImages($data, [$row], $fileToRemove); | |
} else { | |
$this->deleteFileIfExists($fileToRemove); | |
} | |
$data->save(); | |
return response()->json([ | |
'data' => [ | |
'status' => 200, | |
'message' => __('voyager::media.file_removed'), | |
], | |
]); | |
} catch (Exception $e) { | |
$code = 500; | |
$message = __('voyager::generic.internal_error'); | |
if ($e->getCode()) { | |
$code = $e->getCode(); | |
} | |
if ($e->getMessage()) { | |
$message = $e->getMessage(); | |
} | |
return response()->json([ | |
'data' => [ | |
'status' => $code, | |
'message' => $message, | |
], | |
], $code); | |
} | |
} | |
/** | |
* Remove translations, images and files related to a BREAD item. | |
* | |
* @param \Illuminate\Database\Eloquent\Model $dataType | |
* @param \Illuminate\Database\Eloquent\Model $data | |
* | |
* @return void | |
*/ | |
protected function cleanup($dataType, $data) | |
{ | |
// Delete Translations, if present | |
if (is_bread_translatable($data)) { | |
$data->deleteAttributeTranslations($data->getTranslatableAttributes()); | |
} | |
// Delete Images | |
$this->deleteBreadImages($data, $dataType->deleteRows->whereIn('type', ['image', 'multiple_images'])); | |
// Delete Files | |
foreach ($dataType->deleteRows->where('type', 'file') as $row) { | |
if (isset($data->{$row->field})) { | |
foreach (json_decode($data->{$row->field}) as $file) { | |
$this->deleteFileIfExists($file->download_link); | |
} | |
} | |
} | |
// Delete media-picker files | |
$dataType->rows->where('type', 'media_picker')->where('details.delete_files', true)->each(function ($row) use ($data) { | |
$content = $data->{$row->field}; | |
if (isset($content)) { | |
if (!is_array($content)) { | |
$content = json_decode($content); | |
} | |
if (is_array($content)) { | |
foreach ($content as $file) { | |
$this->deleteFileIfExists($file); | |
} | |
} else { | |
$this->deleteFileIfExists($content); | |
} | |
} | |
}); | |
} | |
/** | |
* Delete all images related to a BREAD item. | |
* | |
* @param \Illuminate\Database\Eloquent\Model $data | |
* @param \Illuminate\Database\Eloquent\Model $rows | |
* | |
* @return void | |
*/ | |
public function deleteBreadImages($data, $rows, $single_image = null) | |
{ | |
$imagesDeleted = false; | |
foreach ($rows as $row) { | |
if ($row->type == 'multiple_images') { | |
$images_to_remove = json_decode($data->getOriginal($row->field), true) ?? []; | |
} else { | |
$images_to_remove = [$data->getOriginal($row->field)]; | |
} | |
foreach ($images_to_remove as $image) { | |
// Remove only $single_image if we are removing from bread edit | |
if ($image != config('voyager.user.default_avatar') && (is_null($single_image) || $single_image == $image)) { | |
$this->deleteFileIfExists($image); | |
$imagesDeleted = true; | |
if (isset($row->details->thumbnails)) { | |
foreach ($row->details->thumbnails as $thumbnail) { | |
$ext = explode('.', $image); | |
$extension = '.'.$ext[count($ext) - 1]; | |
$path = str_replace($extension, '', $image); | |
$thumb_name = $thumbnail->name; | |
$this->deleteFileIfExists($path.'-'.$thumb_name.$extension); | |
} | |
} | |
} | |
} | |
} | |
if ($imagesDeleted) { | |
event(new BreadImagesDeleted($data, $rows)); | |
} | |
} | |
/** | |
* Order BREAD items. | |
* | |
* @param string $table | |
* | |
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View | |
*/ | |
public function order(Request $request) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Check permission | |
$this->authorize('edit', app($dataType->model_name)); | |
if (!isset($dataType->order_column) || !isset($dataType->order_display_column)) { | |
return redirect() | |
->route("voyager.{$dataType->slug}.index") | |
->with([ | |
'message' => __('voyager::bread.ordering_not_set'), | |
'alert-type' => 'error', | |
]); | |
} | |
$model = app($dataType->model_name); | |
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { | |
$model = $model->withTrashed(); | |
} | |
$results = $model->orderBy($dataType->order_column, $dataType->order_direction)->get(); | |
$display_column = $dataType->order_display_column; | |
$dataRow = Voyager::model('DataRow')->whereDataTypeId($dataType->id)->whereField($display_column)->first(); | |
$view = 'voyager::bread.order'; | |
if (view()->exists("voyager::$slug.order")) { | |
$view = "voyager::$slug.order"; | |
} | |
return Voyager::view($view, compact( | |
'dataType', | |
'display_column', | |
'dataRow', | |
'results' | |
)); | |
} | |
public function update_order(Request $request) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
// Check permission | |
$this->authorize('edit', app($dataType->model_name)); | |
$model = app($dataType->model_name); | |
$order = json_decode($request->input('order')); | |
$column = $dataType->order_column; | |
foreach ($order as $key => $item) { | |
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model))) { | |
$i = $model->withTrashed()->findOrFail($item->id); | |
} else { | |
$i = $model->findOrFail($item->id); | |
} | |
$i->$column = ($key + 1); | |
$i->save(); | |
} | |
} | |
public function action(Request $request) | |
{ | |
$slug = $this->getSlug($request); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
$action = new $request->action($dataType, null); | |
return $action->massAction(explode(',', $request->ids), $request->headers->get('referer')); | |
} | |
/** | |
* Get BREAD relations data. | |
* | |
* @param Request $request | |
* | |
* @return mixed | |
*/ | |
public function relation(Request $request) | |
{ | |
$slug = $this->getSlug($request); | |
$page = $request->input('page'); | |
$on_page = 50; | |
$search = $request->input('search', false); | |
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first(); | |
$method = $request->input('method', 'add'); | |
$model = app($dataType->model_name); | |
if ($method != 'add') { | |
$model = $model->find($request->input('id')); | |
} | |
$this->authorize($method, $model); | |
$rows = $dataType->{$method.'Rows'}; | |
foreach ($rows as $key => $row) { | |
if ($row->field === $request->input('type')) { | |
$options = $row->details; | |
$model = app($options->model); | |
$skip = $on_page * ($page - 1); | |
// If search query, use LIKE to filter results depending on field label | |
if ($search) { | |
// If we are using additional_attribute as label | |
if (in_array($options->label, $model->additional_attributes ?? [])) { | |
$relationshipOptions = $model->all(); | |
$relationshipOptions = $relationshipOptions->filter(function ($model) use ($search, $options) { | |
return stripos($model->{$options->label}, $search) !== false; | |
}); | |
$total_count = $relationshipOptions->count(); | |
$relationshipOptions = $relationshipOptions->forPage($page, $on_page); | |
} else { | |
$total_count = $model->where($options->label, 'LIKE', '%'.$search.'%')->count(); | |
$relationshipOptions = $model->take($on_page)->skip($skip) | |
->where($options->label, 'LIKE', '%'.$search.'%') | |
->get(); | |
} | |
} else { | |
$total_count = $model->count(); | |
$relationshipOptions = $model->take($on_page)->skip($skip)->get(); | |
} | |
$results = []; | |
if (!$row->required && !$search) { | |
$results[] = [ | |
'id' => '', | |
'text' => __('voyager::generic.none'), | |
]; | |
} | |
foreach ($relationshipOptions as $relationshipOption) { | |
$results[] = [ | |
'id' => $relationshipOption->{$options->key}, | |
'text' => $relationshipOption->{$options->label}, | |
]; | |
} | |
return response()->json([ | |
'results' => $results, | |
'pagination' => [ | |
'more' => ($total_count > ($skip + $on_page)), | |
], | |
]); | |
} | |
} | |
// No result found, return empty array | |
return response()->json([], 404); | |
} | |
} |