ldc-portsalaries/app/Http/Controllers/CrudController.php
2021-06-28 11:49:22 +02:00

258 lines
7.9 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\CrudType;
use App\Exceptions\CrudException;
use App\Http\Requests\CrudIndexRequest;
use App\Http\Requests\StoreCrudModel;
use App\Http\Requests\UpdateCrudModel;
use App\Http\Resources\CrudResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Str;
class CrudController extends Controller
{
/** @var \Illuminate\Database\Eloquent\Model */
protected static $modelClass = null;
// Eloquent callbacks
public function indexQuery(Builder $query): Builder
{
return $query;
}
public function storeModel(Model &$model)
{
}
public function storedModel(Model &$model)
{
}
public function updateModel(Model &$model)
{
}
public function updatedModel(Model &$model)
{
}
public function __construct()
{
// AUTH CONTROL TO ROOT POLICY
$this->authorizeResource(static::$modelClass);
$modelClass = static::$modelClass;
if (is_null($modelClass) or !class_exists($modelClass)) {
throw new CrudException(sprintf(
'%s needs the modelClass prop to be a class, %s %s given',
__CLASS__,
gettype($modelClass),
$modelClass
));
}
if (!is_subclass_of($modelClass, Model::class)) {
throw new CrudException(sprintf(
'%s needs the model prop to be a class the extends %s',
__CLASS__,
Model::class
));
}
if (!request()->ajax() and !app()->runningInConsole()) {
self::shareCrudModelsClassesToView();
$this->shareModelClassToView();
$this->shareModelHasImageToView();
$this->shareModelTableToView();
$this->shareModelPropsToView();
}
}
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\Database\Eloquent\Builder */
$models = static::$modelClass::query();
// Search on crud Label column
if ($request->search) {
$model = static::$modelClass;
$col = (new $model())->crudLabelColumn;
$models = $models->where($col, 'LIKE', "%$request->search%");
}
// Sort columns
$tableName = (new static::$modelClass())->getTable();
if ($request->rst) {
Session::remove("crud.$tableName.sort_col");
Session::remove("crud.$tableName.sort_way");
}
if ($request->sort_col) {
Session::put("crud.$tableName.sort_col", $request->sort_col);
Session::save();
}
if ($request->sort_way) {
Session::put("crud.$tableName.sort_way", $request->sort_way);
Session::save();
}
if (
Session::has("crud.$tableName.sort_col") and
Session::has("crud.$tableName.sort_way") and
Schema::hasColumn($tableName, Session::get("crud.$tableName.sort_col"))
) {
$models = $models->orderBy(
Session::get("crud.$tableName.sort_col"),
Session::get("crud.$tableName.sort_way")
);
}
$models = $this->indexQuery($models);
/** @var \Illuminate\Pagination\AbstractPaginator */
$models = $models->paginate(config('crud.paginate', 15));
if ($request->ajax()) {
return response()->json(CrudResource::collection($models));
} else {
$models = $models->withQueryString();
return view('crud.index', compact('models'));
}
}
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function show(Model $model)
{
return view('crud.show', compact('model'));
}
public function create()
{
return view('crud.create');
}
public function store(StoreCrudModel $request)
{
$modelClass = static::$modelClass;
$model = new $modelClass();
$model->fill($request->validated());
$this->storeModel($model);
$model->saveOrFail();
$model->saveRelations($request);
$this->storedModel($model);
return \redirect()->route(sprintf('bo.%s.edit', $model->getTable()), $model)
->with('success', trans(':model a bien été enregisté.', ['model' => $model->getModelName()]));
}
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function edit(Model $model)
{
return view('crud.edit', compact('model'));
}
public function update(UpdateCrudModel $request, Model $model)
{
$model->fill($request->validated());
$this->updateModel($model);
$model->saveOrFail();
$model->saveRelations($request);
$this->updatedModel($model);
return \redirect()->route(sprintf('bo.%s.edit', $model->getTable()), $model)
->with('success', trans(':model a bien été enregisté.', ['model' => $model->getModelName()]));
}
public function destroy(Model $model)
{
if ($restrict = $model->gotHasManyRelationWithRestrictOnDelete()) {
return redirect()->back()
->with('error', trans(
':model n\'as pas pu être supprimé car il est encore associé avec des :associated',
[
'model' => $model->getModelName(),
'associated' => Str::plural($restrict)
]
));
}
if ($model->delete()) {
return \redirect()->route(sprintf('bo.%s.index', $model->getTable()))
->with('warning', trans(':model a bien été supprimé.', ['model' => $model->getModelName()]));
} else {
return redirect()->back()
->with('error', trans(':model n\'as pas pu être supprimé', ['model' => $model->getModelName()]));
}
}
public function getModelClass()
{
return static::$modelClass;
}
/**
* Get the current model class
*
* @return void
*/
public static function shareCrudModelsClassesToView(): void
{
$models = [];
foreach (File::allFiles(\app_path('Http/Controllers')) as $file) {
$class = sprintf('App\Http\Controllers\%s', \substr($file->getFilename(), 0, -4));
if (is_subclass_of($class, CrudController::class) and $class::$modelClass) {
$models[] = $class::$modelClass;
}
}
View::share('modelsClasses', $models);
}
/**
* Get the current model class
*
* @return void
*/
private function shareModelClassToView(): void
{
View::share('modelClass', static::$modelClass);
}
/**
* Get the current model class
*
* @return void
*/
private function shareModelHasImageToView(): void
{
/** @var \Illuminate\Database\Eloquent\Model $model */
$model = static::$modelClass;
View::share('hasImage', (bool)collect((new $model())->getEditableProperties())->filter(function ($prop) {
return $prop['type']->equals(CrudType::image());
})->count());
}
/**
* Get the current model table
*
* @return void
*/
private function shareModelTableToView(): void
{
/** @var \Illuminate\Database\Eloquent\Model $model */
$model = static::$modelClass;
View::share('modelTable', (new $model())->getTable());
}
/**
* Get the current model properties
*
* @return void
*/
private function shareModelPropsToView(): void
{
$model = static::$modelClass;
View::share('props', (new $model())->getEditableProperties());
}
}