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(); } /*********************/ /* */ /*********************/ $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); } } /**********************/ /* */ /**********************/ 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(); $model->type = $this->modelType; } 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 ); $model->hasPublications = $this->modelHasPublications; 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) { if(is_array($request->$key_date)) { 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]; if(isset($dateTimeValues[0])) { $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(\Auth::user()){ 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 .= "  "; } if(isset($element->lastChild)) { $icon = "└"; } else { $icon = "├"; } $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`)')); if(key_exists('limit', $options)) { $years = $years->limit($options['limit']); } $years = $years->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); } }