Feuerwehr-eppingen/app/Http/Controllers/ExtendedController.php
Marco Glietsch 369e9fb0af Hinzugefügt
- Berechtigungen für Kurzmitteilungen
- Adminscript für Modelle ohne Veröffentlichungen angepasst
2020-11-19 21:45:01 +01:00

1931 lines
45 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers;
use App\Helpers\QuickLoginHelper;
use App\Models\Document;
use App\Models\ExtendedModel;
use App\Models\User;
use Illuminate\Http\Request;
//use Illuminate\Support\Facades\View;
use Illuminate\View\View;
use App\Logic\Document\DocumentRepository;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Validator;
use Response;
use App\Models\Tag;
use App\Models\Post;
use App\Models\QuickLogin;
use App\Helpers\AccessHelper as Access;
use App\Helpers\URLHelper;
use App\Helpers\DateHelper;
use App\Helpers\PublishHelper;
use Auth;
use \Carbon\Carbon;
class MessageType
{
const Success = "success";
const Info = "info";
const Warning = "warning";
const Error = "error";
}
class ExtendedController extends Controller
{
// Model
protected $modelClass;
protected $modelType;
protected $modelData;
protected $modelHasFiles = true;
protected $modelHasPublications = true;
// URL options
protected $url;
protected $route;
protected $indexOptions;
protected $adminIndexOptions;
protected $storeOptions;
protected $updateOptions;
protected $deleteOptions;
protected $detailsOptions;
protected $publishOptions;
protected $wizardOptions;
protected $messages = [];
protected $tagTypes = [];
protected function __construct()
{
$this->middleware(function ($request, $next) {
$this->prepareModelData();
return $next($request);
});
}
/*********/
/* Views */
/*********/
protected function hook_before_action_indexAjax(Request &$request)
{
}
protected function hook_after_action_indexAjax(&$models, View &$view)
{
}
public function indexAjax(Request $request)
{
$this->hook_before_action_indexAjax($request);
// Model erstellen
$model = new $this->modelClass;
if(method_exists($model, 'trashed') && Access::isAdmin())
{
$model = $model->withTrashed();
}
/*********************/
/* <MODEL SORTIEREN> */
/*********************/
$orderColumn = null;
$orderDirection = null;
$model_type = $this->getModelClassString($this->modelClass);
$foreign_type = null;
$pivot_table = null;
// Wurde eine Sortierspalte mit der Seitenanfrage übergeben?
if($request->input('orderBy'))
{
$orderColumn = $request->input('orderBy');
}
// Wenn nicht wird die Standard Sortierspalte aus den Model-Eigenschaften verwendet
else if(key_exists('orderBy', $this->adminIndexOptions))
{
$orderColumn = $this->adminIndexOptions['orderBy'];
}
// Wenn eine Sortierspalte definiert wurde, wird noch die Sortierrichtung festgelegt
// und dem Model die Sortierung mitgeteilt
if($orderColumn != null)
{
// Wurde eine Sortierrichtung mit der Seitenanfrage übergeben?
if($request->input('orderDirection'))
{
$orderDirection = $request->input('orderDirection');
}
// Wenn nicht wird die Standard Sortierrichtung aus den Model-Eigenschaften verwendet
else if(key_exists('orderDirection', $this->adminIndexOptions))
{
$orderDirection = $this->adminIndexOptions['orderDirection'];
}
// Wenn nicht, wird standardmäßig aufsteigend sortiert
else
{
$orderDirection = 'ASC';
}
// Weise dem Model die Sortierung zu, falls es sich um eine gültige Spalte handelt
if(key_exists($orderColumn, $this->modelData))
{
// Die Sortierspalte ist eine Relation
if(key_exists('foreign', $this->modelData[$orderColumn]))
{
// Es wurde eine Model-Klasse angegeben
if(key_exists('class', $this->modelData[$orderColumn]['foreign']))
{
$conditions = array();
if(key_exists('conditions', $this->modelData[$orderColumn]['foreign']))
{
$conditions = $this->modelData[$orderColumn]['foreign']['conditions'];
}
$foreign_type = $this->getModelClassString($this->modelData[$orderColumn]['foreign']['class']);
$pivot_table = $model_type . '_' . $foreign_type;
$model = $model->join("$pivot_table as $pivot_table", function ($join) use ($model_type, $pivot_table)
{
$join->on($model_type . 's.id', $pivot_table . '.' . $model_type . '_id');
})
->join($foreign_type . 's as ' . $foreign_type . 's', function ($join) use ($model_type, $foreign_type, $pivot_table, $conditions)
{
$join->on($pivot_table . '.' . $foreign_type . '_id', $foreign_type . 's.id');
foreach($conditions as $condition)
{
$join->where($foreign_type . 's.' . $condition['column'], $condition['value']);
}
})
->orderBy($foreign_type . 's.' . $this->modelData[$orderColumn]['foreign']['column'], $orderDirection)
->addSelect($foreign_type . 's.' . $this->modelData[$orderColumn]['foreign']['column']);
}
}
// Die Sortierspalte gehört zum Model
else
{
$model = $model->orderBy($orderColumn, $orderDirection);
}
}
else if(key_exists('foreign', $this->adminIndexOptions['listdata'][$orderColumn]))
{
if(key_exists('model', $this->adminIndexOptions['listdata'][$orderColumn]['foreign']))
{
switch($this->adminIndexOptions['listdata'][$orderColumn]['foreign']['model'])
{
case 'audits':
$model = $model->orderBy('users.' . $this->adminIndexOptions['listdata'][$orderColumn]['foreign']['column'], $orderDirection)
->addSelect('users.' . $this->adminIndexOptions['listdata'][$orderColumn]['foreign']['column']);
break;
}
}
}
else if($orderColumn == 'datetime')
{
$model = $model->orderBy($orderColumn, $orderDirection);
}
}
/**********************/
/* </MODEL SORTIEREN> */
/**********************/
if($this->modelClass == Post::class || $this->modelClass == Tag::class)
{
$model = $model->join('users', function ($join) use ($model_type)
{
$join->on($model_type . 's.user_id', 'users.id');
})
->addSelect('users.name as username');
}
if(($this->modelClass == Post::class) || ($this->modelClass == Tag::class))
{
$model = $model->where($model_type . 's.type', $this->modelType);
$model = $model->with('tags');
}
$model = $model->addSelect($model_type . 's.*');
if(Access::hasAdminPermission($this->modelType))
{
// Der Admin hat keine Einschränkungen
}
else if(Access::hasModeratorPermission($this->modelType)
&& ($this->modelClass == Post::class)
)
{
// Wenn der Benutzer nur Moderatorrechte besitzt, bekommt er nur Posts angezeigt,
// die dieselbe Abteilung und Instanz haben wie er selbst
$user = User::find(Access::currentUserId());
$departments = array();
$user->departments->each(function ($d) use (&$departments)
{
$departments[] = $d->id;
});
$instances = array();
$user->instances->each(function ($i) use (&$instances)
{
$instances[] = $i->id;
});
$model = $model->join('post_tag as post_tag', function ($join)
{
$join->on('post_tag.post_id', 'posts.id');
})
->join('tags as tags', function ($join) use ($departments)
{
$join->on('post_tag.tag_id', 'tags.id')
->where('tags.type', 'abteilung')
->whereIn('tags.id', $departments);
});
// Überprüfe, ob in dem Model eine Instanz vokommt
// Falls ja, wird die Benutzerberechtigung der Instanz berücksichtigt
if(in_array('instanz', $this->tagTypes))
{
$model = $model->join('post_tag as post_tag2', function ($join)
{
$join->on('post_tag2.post_id', 'posts.id');
})
->join('tags as tags2', function ($join) use ($instances)
{
$join->on('post_tag2.tag_id', 'tags2.id')
->where('tags2.type', 'instanz')
->whereIn('tags2.id', $instances);
});
}
}
else
{
// Wenn der Benutzer nur Autorrechte besitzt, bekommt er nur Posts seine eigenen Posts angezeigt,
$model = $model->where('user_id', Access::currentUserId());
}
// Suchfunktion
if($request->input('search') != '')
{
$model = $model->search($request->input('search'));
}
if(key_exists('paginate', $this->adminIndexOptions))
{
$itemsPerPage = $this->adminIndexOptions['paginate'];
if($request->input('itemsPerPage'))
{
$itemsPerPage = $request->input('itemsPerPage');
}
$model = $model->paginate($itemsPerPage);
}
else
{
$model = $model->get();
}
$model->each(function ($m)
{
$this->prepareModel($m);
});
if(view()->exists($this->url . '.list'))
{
$viewName = $this->url . '.list';
}
else
{
$viewName = 'inc.admin.listModel';
}
$view = $this->createView($viewName, $request);
$listData = $this->adminIndexOptions['listdata'];
foreach($listData as $key => $options)
{
$data = $listData[$key];
if(key_exists($key, $this->modelData))
{
$listData[$key] = $this->modelData[$key];
}
foreach($data as $optionname => $option)
{
$listData[$key][$optionname] = $option;
}
}
$view->with('orderColumn', $orderColumn);
$view->with('orderDirection', $orderDirection);
$view->with('listdata', $listData);
$view->with('url', $this->route);
$this->hook_after_action_indexAjax($model, $view);
$view->with('models', $model);
return $this->createJSONResponse(
$view->render(),
$model
);
}
protected function hook_before_action_index(Request &$request)
{
}
protected function hook_after_action_index(&$models, View &$view)
{
}
public function index(Request $request)
{
$this->hook_before_action_index($request);
$model = $this->getModels($request, 'all');
$this->prepareModel2($model);
$viewName = "inc.views.index";
if(key_exists('view', $this->indexOptions))
{
$viewName = $this->indexOptions['view'];
}
$view = $this->createView($viewName, $request, true);
$this->hook_after_action_index($model, $view);
$view->with('models', $model);
return $view;
}
protected function hook_before_action_show(Request &$request, $slug)
{
}
protected function hook_after_action_show(&$model, View &$view)
{
}
public function show(Request $request, $slug)
{
$this->hook_before_action_show($request, $slug);
$model = $this->newModel()
->where('slug', $slug)
->first();
$model->test = '213';
if($model == null)
{
abort(404);
}
$this->prepareModel2($model);
$model->isMainPost = true;
// View auswählen
$viewName = "inc.views.detail";
if(key_exists('view', $this->detailsOptions))
{
$viewName = $this->detailsOptions['view'];
}
$view = $this->createView($viewName, $request);
$this->hook_after_action_show($model, $view);
$view->with('model', $model);
return $view;
}
protected function hook_after_action_indexAdmin(View &$view)
{
}
public function indexAdmin()
{
if(Input::get('page'))
{
$page = Input::get('page');
}
else
{
$page = 1;
}
if(view()->exists($this->url . '.index'))
{
$viewName = $this->url . '.index';
}
else
{
$viewName = 'inc.admin.indexModel';
}
$view = $this->createView($viewName);
$view->with('page', $page);
$view->with('itemsPerPage', $this->adminIndexOptions['paginate']);
$this->hook_after_action_indexAdmin($view);
return $view;
}
protected function hook_after_action_create(&$model)
{
}
public function create()
{
if($this->modelClass == Post::class)
{
$model = $this->newModel()->create();
}
else
{
$model = $this->newModel();
}
$model->save();
$model = $this->prepareModel($model);
$this->hook_after_action_create($model);
return $this->createJSONResponse(
$this->renderEditView($model, ['action' => 'create', 'wizard' => true])
);
}
protected function hook_before_renderCreateView(&$vars)
{
}
protected function hook_after_renderCreateView(&$model, View &$view)
{
}
protected function renderCreateView($vars = array())
{
$this->hook_before_renderCreateView($vars);
if(view()->exists($this->url . '.ajaxForm'))
{
$viewName = $this->url . '.ajaxForm';
}
else
{
$viewName = 'inc.admin.crudModal';
}
$view = $this->createView($viewName);
$view->with('form', $this->modelData);
if(count($vars) > 0)
{
foreach($vars as $key => $value)
{
$view->with($key, $value);
}
}
$view->with('action', 'create');
$model = $this->newModel();
$this->hook_after_renderCreateView($model, $view);
$isPost = Schema::hasColumn($model->getTable(), 'published');
$view->with('isPost', $isPost);
return $view->render();
}
protected function hook_before_action_details(Request &$request, $id)
{
}
protected function hook_after_action_details(&$model, View &$view)
{
}
public function details(Request $request, $id)
{
$this->hook_before_action_details($request, $id);
$model = $this->modelClass::find($id);
$this->prepareModel($model);
$listData = $this->modelData;
if(isset($model->id))
{
$listData = array_reverse($listData);
$listData['id'] = [
'label' => 'ID',
'type' => 'inputText',
];
$listData = array_reverse($listData);
}
$model = $this->prepareModel($model);
if(view()->exists($this->url . '.detailsAdmin'))
{
$viewName = $this->url . '.detailsAdmin';
}
else
{
$viewName = 'inc.admin.detailsModel';
}
$view = $this->createView($viewName, $request);
$view->with('data', $listData);
$this->hook_after_action_details($model, $view);
$view->with('model', $model);
return $this->createJSONResponse(
$view->render()
);
}
protected function hook_before_renderEditView(&$vars)
{
}
protected function hook_after_renderEditView(&$model, View &$views)
{
}
protected function renderEditView($model, $vars = array())
{
$this->hook_before_renderEditView($vars);
if(view()->exists('inc.admin.' . $this->url . '.ajaxForm'))
{
$viewName = 'inc.admin.' . $this->url . '.ajaxForm';
}
else
{
$viewName = 'inc.admin.crudModal';
}
$view = $this->createView($viewName);
if(count($vars) > 0)
{
foreach($vars as $key => $value)
{
$view->with($key, $value);
}
}
$isPost = Schema::hasColumn($model->getTable(), 'published');
$view->with('isPost', $isPost);
// Wenn es ein Post Model ist, dann wird noch der Quick-Login aktiviert
if($this->modelClass == Post::class)
{
// Überprüfe, ob es bereits einen entsprechenden Hash gibt
$quickLogin = QuickLoginHelper::createSession($this->modelType, $model->id, Access::currentUserId());
if(!$quickLogin)
{
$quickLogin = new QuickLogin();
$quickLogin->post_type = $this->modelType;
$quickLogin->post_id = $model->id;
$quickLogin->user_id = Access::currentUserId();
// Hash erzeugen
$hash = time() . " " . $this->modelType . " " . $model->id . " " . Access::currentUserId();
$hash = hash('md5', $hash);
$quickLogin->key = $hash;
}
$quickLogin->setUpdatedAt(Carbon::now());
$quickLogin->save();
$model->quickLogin = $quickLogin->key;
}
$view->with('form', $this->modelData);
$view->with('wizardOptions', $this->wizardOptions);
if(is_array($this->updateOptions))
{
if(array_key_exists('view', $this->updateOptions))
{
$view->with('view', $this->updateOptions['view']);
}
}
if(!array_key_exists('action', $vars))
{
$view->with('action', 'edit');
}
$this->hook_after_renderEditView($model, $view);
$view->with('model', $model);
return $view->render();
}
protected function hook_before_action_edit(Request &$request, $id)
{
}
protected function hook_after_action_edit(&$model)
{
}
public function edit(Request $request, $id)
{
$this->hook_before_action_edit($request, $id);
$wizard = false;
if(isset($request['wizard']))
{
$wizard = true;
}
if(method_exists($this->modelClass, 'withTrashed'))
{
$model = $this->modelClass::withTrashed()->find($id);
}
else
{
$model = $this->modelClass::find($id);
}
$model = $this->prepareModel($model);
$this->hook_after_action_edit($model);
return $this->createJSONResponse(
$this->renderEditView($model, ['wizard' => $wizard])
);
}
protected function hook_before_action_validateFormData(Request &$request, $id)
{
}
protected function hook_after_action_validateFormData(&$model)
{
}
protected function hook_error_validateFormData(&$model)
{
}
public function validateFormData(Request $request, $id)
{
$this->hook_before_action_validateFormData($request, $id);
if(isset($request['wizard']))
{
$action = 'CREATE';
}
else
{
$action = 'UPDATE';
}
$request = $this->prepareRequest($request);
switch($this->modelClass)
{
case Tag::class:
case Post::class:
$model = $this->modelClass::withTrashed()->find($id);
$data = $request->all();
break;
default:
$model = $this->modelClass::find($id);
$data = $request->except(['permissions', 'type', 'wizard', 'user_id']);
break;
}
$validator = Validator::make($request->all(), $this->getValidationRules($action));
$model->fill($data);
$model = $this->prepareModel($model, $request);
$model = $this->getForeignDataFromRequest($model, $request);
$wizard = false;
if(isset($request['wizard']))
{
$wizard = true;
}
if($validator->fails())
{
$this->hook_error_validateFormData($model);
$this->addMessageError(
__("messages.form error"),
__("messages.please fill the form correct")
);
return $this->createJSONResponse(
$this->renderEditView($model, ['errors' => $validator->getMessageBag(), 'wizard' => $wizard])
);
}
else
{
$this->hook_after_action_validateFormData($model);
$this->addMessageInfo(
__("messages.form ok"),
__("messages.form filled correct")
);
return $this->createJSONResponse(
$this->renderEditView($model, ['wizard' => $wizard])
);
}
}
/*******************/
/* Model sortieren */
/*******************/
protected function hook_before_action_moveUp(Request &$request, $id)
{
}
protected function hook_after_action_moveUp(&$model)
{
}
public function moveUp(Request $request, $id)
{
$this->hook_before_action_moveUp($request, $id);
$model = $this->modelClass::find($id);
$model->moveOrderUp();
$this->hook_after_action_moveUp($model);
return $this->createJSONResponse();
}
protected function hook_before_action_moveDown(Request &$request, $id)
{
}
protected function hook_after_action_moveDown(&$model)
{
}
public function moveDown(Request $request, $id)
{
$this->hook_before_action_moveDown($request, $id);
$model = $this->modelClass::find($id);
$model->moveOrderDown();
$this->hook_after_action_moveDown($model);
return $this->createJSONResponse();
}
/*******************/
/* Model speichern */
/*******************/
protected function hook_before_action_update(Request &$request, $id)
{
}
protected function hook_after_action_update(&$model, Request &$request)
{
}
protected function hook_error_action_update(&$model)
{
}
public function update(Request $request, $id)
{
$this->hook_before_action_update($request, $id);
$wizard = false;
if(isset($request['wizard']))
{
$wizard = true;
$action = 'CREATE';
}
else
{
$action = 'UPDATE';
}
if(method_exists($this->modelClass, 'withTrashed'))
{
$model = $this->modelClass::withTrashed()->find($id);
}
else
{
$model = $this->modelClass::find($id);
}
if(isset($request['restore']))
{
$model->restore();
$this->hook_after_action_update($model, $request);
$this->addMessageSuccess(
__("messages.restored"),
__("messages.:model successfully restored", ['model' => __('models.'.$this->url)])
);
return $this->createJSONResponse();
}
elseif(isset($request['publish_website_action']))
{
$published_website = $request['publish_website_action'] == "true" ? 1 : 0;
$model->disableTimestamps();
$model->published = $published_website;
$model->save();
if($published_website == 1)
{
$this->addMessageSuccess(
__("messages.published"),
__("messages.:model successfully published", ['model' => __('models.'.$this->url)])
);
}
else
{
$this->addMessageSuccess(
__("messages.publication withdrawn"),
__("messages.:model publication successfully withdrawn", ['model' => __('models.'.$this->url)])
);
}
$this->hook_after_action_update($model, $request);
return $this->createJSONResponse();
}
else
{
$validator = Validator::make($request->all(), $this->getValidationRules($action));
$request = $this->prepareRequest($request);
$model = $this->modelFill($model, $request);
if($validator->fails())
{
$model = $this->prepareModel($model);
$this->hook_error_action_update($model);
$this->addMessageError(
__("messages.form error"),
__("messages.please fill the form correct")
);
return $this->createJSONResponse(
$this->renderEditView($model, ['errors' => $validator->getMessageBag(), 'wizard' => $wizard])
);
}
// Speichere den originalen Datensatz ab
$this->saveModel($model, $request);
$this->hook_after_action_update($model, $request);
$this->addMessageSuccess(
__("messages.saved"),
__("messages.:model successfully edited", ['model' => __('models.'.$this->url)]),
true
);
return $this->createJSONResponse(
$this->renderEditView($model, ['errors' => $validator->getMessageBag(), 'wizard' => $wizard])
);
}
}
protected function hook_before_model_save(&$model, Request &$request)
{
}
protected function hook_after_model_save(&$model, Request &$request)
{
}
protected function saveModel($model, $request)
{
$this->hook_before_model_save($model, $request);
$model->save();
$this->saveForeignData($model, $request);
$this->hook_after_model_save($model, $request);
}
/*****************/
/* Model löschen */
/*****************/
protected function hook_before_action_destroy(Request &$request, $id)
{
}
protected function hook_after_action_destroy(&$model)
{
}
public function destroy(Request $request, $id)
{
$this->hook_before_action_destroy($request, $id);
$model = $this->modelClass::find($id);
if($model->type == "" || $request->input('wizard'))
{
$model->forceDelete();
}
else
{
$model->delete();
}
$this->addMessageSuccess(
__("messages.deleted"),
__("messages.:model successfully deleted", ['model' => __('models.'.$this->url)])
);
$this->hook_after_action_destroy($model);
return $this->indexAjax($request);
}
/*******************/
/* Hilfsfunktionen */
/*******************/
protected function modelFill($model, $request)
{
$fields = array();
foreach($this->modelData as $key => $value)
{
if(!array_key_exists('foreign', $value))
{
$keys = explode('.', $key);
$fields[] = end($keys);
}
}
foreach($request->all() as $key => $value)
{
if(Schema::hasColumn($model->getTable(), $key))
{
$model->$key = $value;
}
}
// $model->fill($request->all());
// $model->fill($request->only($fields));
if($this->modelClass == Post::class || $this->modelClass == Tag::class)
{
$model->type = $this->modelType;
}
// Wenn es sich um einen Post ohne Datum/Uhrzeit handelt, wird das Datum der letzten Änderung verwendet
if($this->modelClass == Post::class)
{
if($model->datetime == NULL)
{
$model->datetime = Carbon::now();
}
}
return $model;
}
protected function getValidationRules($action)
{
$rules = array();
foreach($this->modelData as $key => $options)
{
if($options['type'] == 'inputDateTimePicker')
{
if(key_exists('multidate', $options['datepicker']))
{
// if($options['datepicker']['multidate'] && $action == 'CREATE')
{
$dateValidator = 'multidate_format';
}
// else
{
// $dateValidator = 'date_format';
}
}
else
{
$dateValidator = 'date_format';
}
if(key_exists('validation', $options['datepicker']))
{
if(key_exists('rules', $options['datepicker']['validation']))
{
$keys = explode(".", $key . '_date');
$keyname = $keys[count($keys) - 1];
$rule = $options['datepicker']['validation']['rules'];
$formatRule = $dateValidator . ':' . $options['datepicker']['format'];
if(!empty($rule))
{
$rule .= '|';
}
$rule .= $formatRule;
$rules[$keyname] = $rule;
}
}
if(key_exists('validation', $options['time']))
{
if(key_exists('rules', $options['time']['validation']))
{
$keys = explode(".", $key . '_time');
$keyname = $keys[count($keys) - 1];
$rule = $options['time']['validation']['rules'];
$formatRule = $dateValidator . ':' . $options['time']['format'];
if(!empty($rule))
{
$rule .= '|';
}
$rule .= $formatRule;
$rules[$keyname] = $rule;
}
}
}
else if(key_exists('validation', $options))
{
if(key_exists('rules', $options['validation']))
{
$keys = explode(".", $key);
$keyname = $keys[count($keys) - 1];
$rules[$keyname] = $options['validation']['rules'];
}
}
}
return $rules;
}
protected function parseModelDataNames()
{
$data = array();
foreach($this->modelData as $key => $options)
{
$k = explode(".", $key);
if(count($k) > 1)
{
$data[$k[0]][] = $k[1];
}
}
return $data;
}
protected function prepareModel($model, $request = null)
{
$data = $this->parseModelDataNames();
foreach($data as $key => $values)
{
if(is_object($model->$key))
{
foreach($model->$key as $k => $v)
{
$model->$k = $v;
}
}
}
foreach($this->modelData as $key => $options)
{
if($options['type'] == 'inputDateTimePicker')
{
if($model->$key != "")
{
$dateFormat = $options['datepicker']['format'];
$timeFormat = $options['time']['format'];
// Überprüfe, ob das Datums- und Zeitformat korrekt ist
// Format 1: Wie in der xxxConcotrller.php Datei vorgegeben
// Format 2: Das Standardformat der Datenbank
$dateTimeValues = array();
$validator1 = Validator::make([
$key => $model->$key,
], [
$key => "date_format:$dateFormat $timeFormat",
]);
$validator2 = Validator::make([
$key => $model->$key,
], [
$key => "date_format:" . config('formats.datetime.database'),
]);
if($validator1->fails() && $validator2->fails())
{
$values = explode(" ", $model->$key);
$keys = explode(".", $key . '_date');
$keyname = $keys[count($keys) - 1];
$model->$keyname = $values[0];
$keys = explode(".", $key . '_time');
$keyname = $keys[count($keys) - 1];
$model->$keyname = $values[1];
}
else
{
$key_date = $key . '_date';
$key_time = $key . '_time';
$key_array = $key . '_multidates';
$dateTimeValues = array();
if($request)
{
foreach($request->$key_date as $date)
{
$dateTimeValues[] = \Carbon\Carbon::createFromFormat($dateFormat . ' ' . $timeFormat, $date . ' ' . $request->$key_time);
}
}
else
{
$dateTimeValues[] = \Carbon\Carbon::createFromFormat(config('formats.datetime.database'), $model->$key);
}
$keys = explode(".", $key_time);
$keyname_time = $keys[count($keys) - 1];
$model->$keyname_time = ($dateTimeValues[0])->format($options['time']['format']);
$keys = explode(".", $key_date);
$keyname_date = $keys[count($keys) - 1];
$dates = array();
$datetimes = array();
foreach($dateTimeValues as $dtv)
{
$dates[] = $dtv->format($options['datepicker']['format']);
$datetimes[] = $dtv->format(config('formats.datetime.database'));
}
$model->$keyname_date = implode(',', $dates);
$model->$key_array = implode(',', $datetimes);
}
}
}
}
if(!isset($model->type) && ($this->modelClass == Post::class || $this->modelClass == Tag::class))
{
$model->type = $this->modelType;
}
// Überprüfe, ob das Model Dateien und Veröfentlichungen besitzen darf
$model->hasFiles = $this->modelHasFiles;
$model->hasPublications = $this->modelHasPublications;
return $model;
}
protected function prepareModel2(&$model)
{
$model->modeltype = $this->url;
$model->modeltypes = $this->url."s";
}
protected function prepareRequest(Request $request)
{
$data = $this->parseModelDataNames();
foreach($data as $key => $values)
{
$d = array();
foreach($values as $valuename)
{
$d[$valuename] = $request->$valuename;
}
$v = json_encode($d);
$request->request->add([$key => $v]);
}
foreach($this->modelData as $key => $options)
{
if($options['type'] == 'inputDateTimePicker')
{
if(key_exists('datepicker', $options) && key_exists('time', $options))
{
if(key_exists('format', $options['datepicker']) && key_exists('format', $options['time']))
{
$dateKey = $key . '_date';
$dateValue = $request->$dateKey;
$dateValues = explode(",", $dateValue);
$dateFormat = $options['datepicker']['format'];
$timeFormat = $options['time']['format'];
$format = $dateFormat . ' ' . $timeFormat;
$timeKey = $key . '_time';
$timeValue = $request->$timeKey;
$dateTimeValues = array();
foreach($dateValues as $dateValue)
{
$validator = Validator::make([
$dateKey => $dateValue,
$timeKey => $timeValue
], [
$dateKey => 'date_format:' . $dateFormat,
$timeKey => 'date_format:' . $timeFormat,
]);
if($validator->fails())
{
$dateTimeValues[] = "$dateValue $timeValue";
}
else
{
$dateTime = $dateValue . ' ' . $timeValue;
$dateTimeValues[] = \Carbon\Carbon::createFromFormat($format, $dateTime)->format(config('formats.datetime.database'));
}
}
if($request->method() == "PUT")
{
$request->merge([
$key => $dateTimeValues[0],
$dateKey => $dateValues,
$timeKey => $timeValue,
]);
}
else
{
$request->merge([$key => $dateTimeValues]);
}
if(count($dateTimeValues) > 1)
{
$request->merge(['multidate' => $key]);
}
// $request->offsetUnset($dateKey);
// $request->offsetUnset($timeKey);
}
}
}
if($options['type'] == 'inputCheckbox')
{
if(!isset($request[$key]))
{
$request->merge([$key => 0]);
}
}
}
$request->merge(['user_id' => Auth::user()->id]);
return $request;
}
protected function getForeignModel($key, $options, $withPermissions = true)
{
$foreign = $options['foreign'];
$query = new $foreign['class'];
$query = $query->addSelect($foreign['model'] . '.*');
if(key_exists('conditions', $foreign))
{
foreach($foreign['conditions'] as $condition)
{
$column = $condition['column'];
$value = $condition['value'];
if(key_exists('condition', $condition))
{
$query = $query->where($column, $condition['condition'], $value);
}
else
{
$query = $query->where($column, $value);
}
}
}
// Gibt es Zugriffsberechtigungen für das Model, die die Auswahl einschränken?
if(!Access::hasAdminPermission($this->modelType) && $this->modelClass != User::class && $withPermissions)
{
if(method_exists(\Auth::user(), $key))
{
$query = $query->where(function ($q) use ($key)
{
foreach(\Auth::user()->$key as $k => $v)
{
$q->orWhere('id', $v->id);
}
});
}
}
// Sortiere nach Datenbankspalte
if(key_exists('order', $foreign))
{
$order = $foreign['order'];
// Überprüfe, ob die Sortierspalte existiert
if(Schema::hasColumn($foreign['model'], $order['column']))
{
$query = $query->orderBy($order['column'], $order['direction']);
}
}
// Wenn es eine verkettete Liste ist werden zunächst nur die Wurzelelemente ausgelesen
if(key_exists('linkedList', $foreign))
{
$query = $query->isRootElement();
}
$fm = $query->get();
// dd($query->toSql(), $query->getBindings());
// Wandle das Objekt in ein Array um, damit es später über 'usort' sortiert werden kann
$foreignModel = array();
foreach($fm as $f)
{
$foreignModel[] = $f;
// Wenn es eine verkettete Liste ist werden die Kindelemente ausgelesen
if(key_exists('linkedList', $foreign))
{
$childs = $this->getChildModel($f);
if(count($childs))
{
$foreignModel = array_merge($foreignModel, $childs);
}
}
}
// Überprüfe, ob ein Label angegeben wurde
if(key_exists('label', $foreign))
{
foreach($foreignModel as $k => $vals)
{
// Zerlege das Label
$labels = explode(" ", $foreign['label']);
// Hole die Werte für die einzelnen Labels
foreach($labels as $labelKey => $labelValue)
{
if(isset($foreignModel[$k]->$labelValue))
{
$labelValue = $foreignModel[$k]->$labelValue;
}
elseif(isset($foreignModel[$k]->content->$labelValue))
{
$labelValue = $foreignModel[$k]->content->$labelValue;
}
$labels[$labelKey] = $labelValue;
}
$foreignModel[$k]->label = implode(" ", $labels);
}
}
// Sortiere nach json- oder label-Spalte
if(key_exists('order', $foreign))
{
$order = $foreign['order'];
if(!Schema::hasColumn($foreign['model'], $order['column']))
{
$column = $order['column'];
usort($foreignModel, function ($a, $b) use ($order, $column)
{
if($order['direction'] === 'DESC')
{
return -strcmp($a->$column, $b->$column);
}
else
{
return strcmp($a->$column, $b->$column);
}
});
}
}
// Wenn es eine verkettete Liste werden die Kindelemente eingerückt
if(key_exists('linkedList', $foreign))
{
$column = $foreign['column'];
$icon = "";
foreach($foreignModel as $element)
{
if(isset($element->level))
{
$indent = "";
for($i = 0; $i < $element->level; $i++)
{
$indent .= "&nbsp;&nbsp;";
}
if(isset($element->lastChild))
{
$icon = "&boxur;";
}
else
{
$icon = "&boxvr;";
}
$element->$column = $indent . $icon . $element->$column;
}
}
}
return $foreignModel;
}
protected function prepareModelData()
{
if(isset($this->modelData))
{
if(count($this->modelData) > 0)
{
foreach($this->modelData as $key => $options)
{
if(key_exists('foreign', $options))
{
$this->modelData[$key]['foreign']['models'] = $this->getForeignModel($key, $options);
if(key_exists('conditions', $options['foreign']))
{
foreach($options['foreign']['conditions'] as $condition)
{
if($condition['column'] == 'type')
{
$this->tagTypes[] = $condition['value'];
}
}
}
}
if($options['type'] == 'checkboxSelection')
{
$this->modelData[$key]['models'] = $this->modelData[$key]['foreign']['models'];
$this->modelData[$key]['name'] = $this->modelData[$key]['foreign']['model'];
}
}
}
}
}
protected function getChildModel($model, $level = 1)
{
$elements = array();
$children = $model->children()->get();
$i = 0;
$childrenCount = count($children);
foreach($children as $child)
{
if($i == 0)
{
$child->firstChild = true;
}
if(($i + 1) >= $childrenCount)
{
$child->lastChild = true;
}
$child->level = $level;
$elements[] = $child;
$subchilds = $this->getChildModel($child, ($level + 1));
if(count($subchilds))
{
$elements = array_merge($elements, $subchilds);
}
$i++;
}
return $elements;
}
protected function getForeignDataFromRequest($model, $request)
{
foreach($this->modelData as $key => $options)
{
if(key_exists('foreign', $options))
{
$foreign = $options['foreign'];
$foreignModel = $foreign['model'];
$foreignClass = $foreign['class'];
if(method_exists($model->$foreignModel(), 'sync'))
{
$fm = new $foreignClass;
$fm = $fm->find($request[$foreignModel]);
$model->setRelation($foreignModel, $fm);
}
}
}
return $model;
}
protected function saveForeignData($model, $request)
{
foreach($this->modelData as $key => $options)
{
if(key_exists('foreign', $options))
{
$foreign = $options['foreign'];
$foreignModel = $foreign['model'];
$foreignClass = $foreign['class'];
if(method_exists($model->$foreignModel(), 'sync'))
{
$requestModel = $request[$foreignModel];
$modelClass = $this->getModelClassString($this->modelClass) . "s";
// Wenn das Model auf sich selber verweist, wird die entsprechende ID aus dem Array entfernt
if($modelClass == $foreignModel)
{
if(is_array($requestModel))
{
if(($key = array_search($model->id, $requestModel)) !== false)
{
unset($requestModel[$key]);
}
}
}
$model->$foreignModel()->sync($requestModel);
$model->$foreignModel;
}
}
}
}
protected function newModel()
{
$model = new $this->modelClass;
return $model;
}
protected function getModels(Request $request, $withImages)
{
$model = $this->newModel();
if(!is_string($withImages))
{
if($withImages == true)
{
$model = $model->withImages();
}
else
{
$model = $model->withoutImages();
}
}
$model = $this->filterModel($model, $this->indexOptions);
$model = $this->orderModel($model, $this->indexOptions);
if(($this->modelClass == Post::class) || ($this->modelClass == Tag::class))
{
$model = $model->isType($this->modelType);
$model = $model->with('tags');
}
if(key_exists('paginate', $this->indexOptions))
{
$model = $model->paginate($this->indexOptions['paginate']);
}
else
{
$model = $model->get();
}
return $model;
}
protected function orderModel($model, $options)
{
if(key_exists('orderBy', $options))
{
if(key_exists('orderDirection', $options))
{
$direction = $options['orderDirection'];
}
else
{
$direction = 'ASC';
}
$model = $model->orderBy($options['orderBy'], $direction);
}
return $model;
}
protected function filterModel($model, $options)
{
// Filter anwenden
if(key_exists('filter', $options))
{
// Schleife über alle Filter
foreach($options['filter'] as $key => $opts)
{
// Überprüfe, ob der Filter ein Foreign Key ist
if(key_exists($key, $this->modelData))
{
$typeColumn = $this->modelData[$key]['foreign']['conditions'][0]['column'];
$typeValue = $this->modelData[$key]['foreign']['conditions'][0]['value'];
$filterValue = Input::get($typeValue);
if($filterValue)
{
$model = $model->withTag($typeValue, $filterValue);
}
}
elseif($key == 'year')
{
$name = $opts['name'];
$filterValue = Input::get($name);
if($filterValue)
{
$model = $model->whereYear('datetime', $filterValue);
}
}
elseif($key == 'month')
{
$name = $opts['name'];
$filterValue = Input::get($name);
if($filterValue)
{
$model = $model->whereMonth('datetime', $filterValue);
}
}
}
}
return $model;
}
protected function createSidebarLinks($models, $label)
{
$links = array();
foreach($models as $model)
{
$links[] = [
'label' => $model->title,
'url' => URLHelper::create($model),
];
}
$sidebar = [
'label' => $label,
'links' => $links
];
return $sidebar;
}
protected function prepareFilters(Request $request)
{
$filters = array();
$activeFilters = array();
// Überprüfe, ob ein Filter angegeben wurde
if(key_exists('filter', $this->indexOptions))
{
// Schleife über alle Filter
foreach($this->indexOptions['filter'] as $key => $options)
{
$filter = array();
if(key_exists('type', $options))
{
$filter['type'] = $options['type'];
}
else
{
$filter['type'] = 'link';
}
// Überprüfe, ob der Filter ein Foreign Key ist
if(key_exists($key, $this->modelData))
{
if(key_exists('label', $options))
{
$filter['label'] = $options['label'];
}
else
{
$filter['label'] = $this->modelData[$key]['label'];
}
$filter['name'] = $this->modelData[$key]['foreign']['conditions'][0]['value'];
$data = $this->getForeignModel($key, $this->modelData[$key], false);
// Wurde in der URL bereits ein Filterwert übergeben?
$urlFilterValue = $request->input($filter['name']);
foreach($data as $d)
{
$val['value'] = $d->name;
if($urlFilterValue == $d->name)
{
$val['checked'] = true;
}
else
{
$val['checked'] = false;
}
$filter['data'][] = $val;
if($val['checked'] == true)
{
$activeFilters[$filter['name']] = $filter;
}
}
$filters[] = $filter;
}
elseif($key == 'year')
{
$years = $this->newModel()
->select(DB::raw('YEAR(`datetime`) as year'))
->where('type', $this->modelType)
->orderBy('datetime', 'DESC')
->groupBy(DB::raw('YEAR(`datetime`)'))
->get();
$filter['label'] = $options['label'];
$filter['name'] = $options['name'];
// Wurde in der URL bereits ein Filterwert übergeben?
$urlFilterValue = $request->input($filter['name']);
foreach($years as $key => $year)
{
if($year['year'])
{
$val['value'] = $year['year'];
if($urlFilterValue == $year['year'])
{
$val['checked'] = true;
}
else
{
$val['checked'] = false;
}
$filter['data'][] = $val;
if($val['checked'] == true)
{
$activeFilters[$filter['name']] = $filter;
}
}
}
$filters[] = $filter;
}
elseif($key == 'month')
{
$months = $this->newModel()
->select(DB::raw('MONTH(`datetime`) as month'))
->where('type', $this->modelType)
->orderBy('datetime', 'ASC')
->groupBy(DB::raw('MONTH(`datetime`)'))
->get();
$filter['label'] = $options['label'];
$filter['name'] = $options['name'];
// Wurde in der URL bereits ein Filterwert übergeben?
$urlFilterValue = $request->input($filter['name']);
foreach($months as $key => $month)
{
if($month['month'])
{
$val['value'] = $month['month'];
if($urlFilterValue == $month['month'])
{
$val['checked'] = true;
}
else
{
$val['checked'] = false;
}
$filter['data'][] = $val;
if($val['checked'] == true)
{
$activeFilters[$filter['name']] = $filter;
}
}
}
$filters[] = $filter;
}
}
// Erstelle die Links für die Filter
foreach($filters as $filterKey => $filter)
{
foreach($filter['data'] as $dataKey => $data)
{
if($data['checked'])
{
$data['url'] = $this->modelType;
foreach($activeFilters as $key => $activeFilter)
{
if($key != $filter['name'])
{
foreach($activeFilter['data'] as $key2 => $activeData)
{
if($data['url'] == $this->modelType)
{
$data['url'] .= '?';
}
if($activeData['checked'] == true)
{
$data['url'] .= $activeFilter['name'] . '=' . $activeData['value'] . '&';
}
}
}
}
}
else
{
$data['url'] = $this->modelType . "?" . $filter['name'] . "=" . $data['value'];
foreach($activeFilters as $key => $activeFilter)
{
if($key != $filter['name'])
{
foreach($activeFilter['data'] as $key2 => $activeData)
{
if($activeData['checked'] == true)
{
$data['url'] .= '&' . $activeFilter['name'] . '=' . $activeData['value'];
}
}
}
}
}
$filter['data'][$dataKey] = $data;
}
$filters[$filterKey] = $filter;
}
}
return $filters;
}
private function createView($viewName, Request $request = null, $withFilters = false)
{
$view = view($viewName);
$view->with('config', $this->modelData);
$view->with('url', $this->route);
$view->with('modeltype', $this->url);
$view->with('modeltypes', $this->url."s");
if($withFilters)
{
$view->with('filters', $this->prepareFilters($request));
}
return $view;
}
protected function getModelClassString($modelClass)
{
$className = (new \ReflectionClass($modelClass))->getShortName();
return lcfirst($className);
}
/**********************************************/
/* Benachrichtigungen für die Adminoberfläche */
/**********************************************/
protected function clearMessages()
{
$this->messages = array();
}
protected function addMessage($title, $message, $type = MessageType::Success, $prepend = false)
{
$message = [
'title' => $title,
'message' => $message,
'type' => $type,
];
if($prepend)
{
array_unshift($this->messages, $message);
}
else
{
array_push($this->messages, $message);
}
}
protected function addMessageSuccess($title, $message, $prepend = false)
{
$this->addMessage($title, $message, MessageType::Success, $prepend);
}
protected function addMessageInfo($title, $message, $prepend = false)
{
$this->addMessage($title, $message, MessageType::Info, $prepend);
}
protected function addMessageWarning($title, $message, $prepend = false)
{
$this->addMessage($title, $message, MessageType::Warning, $prepend);
}
protected function addMessageError($title, $message, $prepend = false)
{
$this->addMessage($title, $message, MessageType::Error, $prepend);
}
/*****************************************/
/* JSON-Response für die Adminoberfläche */
/*****************************************/
protected function createJSONResponse($html = "", $model = null)
{
// Durchsuche alle Nachrichten auf Fehler
$error = false;
foreach($this->messages as $message)
{
if($message['type'] == MessageType::Error)
{
$error = true;
break;
}
}
$response = [
'status' => [
'error' => $error,
],
'content' => [
'html' => $html,
'models' => $model
],
'messages' => $this->messages
];
return Response::json($response);
}
}