diff --git a/src/Controllers/BadasoCRUDController.php b/src/Controllers/BadasoCRUDController.php index cead5e4d..6dffcc1e 100644 --- a/src/Controllers/BadasoCRUDController.php +++ b/src/Controllers/BadasoCRUDController.php @@ -46,20 +46,18 @@ public function browse(Request $request) // end init table watch table $protected_tables = Badaso::getProtectedTables(); - // $tables = SchemaManager::listTables(); - $tables = Schema::getTables(); - + $tables = SchemaManager::listTables(); $tables_with_crud_data = []; foreach ($tables as $key => $value) { - if (! in_array($value["name"], $protected_tables)) { + + if (!in_array($key, $protected_tables)) { // add table watch config - $config_watch_tables->addWatchTable($value["name"]); - + $config_watch_tables->addWatchTable($key); // end add table watch config $table_with_crud_data = []; - $table_with_crud_data['table_name'] = $value["name"]; - $table_with_crud_data['crud_data'] = Badaso::model('DataType')::where('name', $value["name"])->first(); + $table_with_crud_data['table_name'] = $key; + $table_with_crud_data['crud_data'] = Badaso::model('DataType')::where('name', $key)->first(); $tables_with_crud_data[] = $table_with_crud_data; } } @@ -72,230 +70,229 @@ public function browse(Request $request) } } - // public function read(Request $request) - // { - - // try { - // $request->validate([ - // 'table' => 'required|exists:Uasoft\Badaso\Models\DataType,name', - // ]); - - // $table = $request->input('table', ''); - // $data_type = Badaso::model('DataType')::where('name', $table)->first(); - // $data_rows = $this->dataRowsTypeReplace($data_type->dataRows); - - // $table_fields = SchemaManager::describeTable($table); - // $generated_fields = collect($data_rows)->pluck('field')->toArray(); - - // foreach ($table_fields as $key => $column) { - // $field = $key; - // $column = collect($column)->toArray(); - // if (! in_array($field, $generated_fields)) { - // $data_row['data_type_id'] = $data_type->id; - // $data_row['field'] = $key; - // $data_row['type'] = DataTypeToComponent::convert($column['type']); - // $data_row['displayName'] = Str::studly($field); - // $data_row['required'] = $column['notnull'] ? 1 : 0; - // $data_row['browse'] = 1; - // $data_row['read'] = 1; - // $data_row['edit'] = 0; - // $data_row['add'] = 0; - // $data_row['delete'] = 0; - // $data_row['details'] = '{}'; - // $data_row['order'] = null; - - // $data_rows[] = $data_row; - // } - // } - - // $data_type->data_rows = $data_rows; - - // $data['crud'] = collect($data_type)->toArray(); - - // return ApiResponse::success($data); - // } catch (Exception $e) { - // return APIResponse::failed($e); - // } - // } - - // public function readBySlug(Request $request) - // { - // try { - // $request->validate([ - // 'slug' => 'required|exists:Uasoft\Badaso\Models\DataType,slug', - // ]); - - // $slug = $request->input('slug', ''); - // $data_type = Badaso::model('DataType')::where('slug', $slug)->first(); - // $data_rows = $this->dataRowsTypeReplace($data_type->dataRows); - - // $crud_data = $data_type; - // $crud_data->data_rows = collect($data_rows)->toArray(); - - // $data['crud_data'] = $crud_data; - - // return ApiResponse::success($data); - // } catch (Exception $e) { - // return APIResponse::failed($e); - // } - // } - - // public function edit(Request $request) - // { - // $this->addTablePolymorphism($request); - // DB::beginTransaction(); - - // try { - // $request->validate([ - // 'id' => 'required|exists:Uasoft\Badaso\Models\DataType', - // 'name' => [ - // 'required', - // "unique:Uasoft\Badaso\Models\DataType,name,{$request->id}", - // function ($attribute, $value, $fail) { - // if (! Schema::hasTable($value)) { - // $fail(__('badaso::validation.crud.table_not_found', ['table' => $value])); - // } - // }, - // ], - // 'rows' => 'required', - // 'rows.*.field' => [ - // 'required', - // function ($attribute, $value, $fail) use ($request) { - // if (! Schema::hasColumn($request->name, $value)) { - // $split_attribute = explode('.', $attribute); - // $split_attribute[2] = 'relation_type'; - // $field_to_relation = join('.', $split_attribute); - // if (! $field_to_relation == 'belongs_to_many') { - // $request->{$attribute} == $value ? $value : $fail(__('badaso::validation.crud.table_column_not_found', ['table_column' => "$request->name.{$value}"])); - // } - // } else { - // $table_fields = SchemaManager::describeTable($request->name); - // $field = collect($table_fields)->where('field', $value)->first(); - // $row = collect($request->rows)->where('field', $value)->first(); - // if (! $row['add'] && ! $field['autoincrement'] && $field['notnull'] && is_null($field['default'])) { - // $fail(__('badaso::validation.crud.table_column_not_have_default_value', ['table_column' => "$request->name.{$value}"])); - // } elseif ($row['field'] != 'id' && $field['key'] == 'PRI') { - // $fail(__('badaso::validation.crud.id_table_wrong', ['table_column' => "$request->name.{$value}"])); - // } - // } - // }, - // ], - // 'rows.*.type' => 'required', - // 'rows.*.display_name' => 'required', - // 'display_name_singular' => 'required', - // 'notification.*.event' => ['in:onCreate,onRead,onUpdate,onDelete'], - // 'create_soft_delete' => ['required', 'boolean', function ($att, $val, $failed) use ($request) { - // if (isset($request->name) && $val) { - // if (! Schema::hasColumn($request->name, 'deleted_at')) { - // $failed(__('badaso::validation.crud.table_deleted_at_not_exists', [ - // 'table_name' => $request->name, - // ])); - // } - // } - // }], - // ]); - - // $table_name = $request->input('name'); - - // $data_type = DataType::find($request->input('id')); - - // $data_type->name = $table_name; - // $data_type->slug = $request->input('slug') ?? Str::slug($table_name); - // $data_type->display_name_singular = $request->input('display_name_singular'); - // $data_type->display_name_plural = $request->input('display_name_plural') ?? Str::plural($data_type->display_name_singular); - // $data_type->icon = $request->input('icon'); - // $data_type->model_name = $request->input('model_name'); - // $data_type->policy_name = $request->input('policy_name'); - // $data_type->order_column = $request->input('order_column'); - // $data_type->order_display_column = $request->input('order_display_column'); - // $data_type->order_direction = $request->input('order_direction'); - // $data_type->description = $request->input('description'); - // $data_type->generate_permissions = $request->input('generate_permissions'); - // $data_type->server_side = $request->input('server_side'); - // $data_type->details = $request->input('details'); - // $data_type->controller = $request->input('controller'); - // $data_type->notification = json_encode($request->input('notification')); - // $data_type->is_soft_delete = $request->input('create_soft_delete'); - // $data_type->save(); - - // DataRow::where('data_type_id', $data_type->id)->delete(); - - // $data_rows = $request->input('rows') ?? []; - // $new_data_rows = []; - // foreach ($data_rows as $index => $data_row) { - // $new_data_row = new DataRow(); - // $new_data_row->data_type_id = $data_type->id; - // $new_data_row->field = $data_row['field']; - // $new_data_row->type = $data_row['type']; - // $new_data_row->display_name = $data_row['display_name']; - // $new_data_row->required = isset($data_row['required']) ? $data_row['required'] : false; - // $new_data_row->browse = isset($data_row['browse']) ? $data_row['browse'] : false; - // $new_data_row->read = isset($data_row['read']) ? $data_row['read'] : false; - // $new_data_row->edit = isset($data_row['edit']) ? $data_row['edit'] : false; - // $new_data_row->add = isset($data_row['add']) ? $data_row['add'] : false; - // $new_data_row->delete = isset($data_row['delete']) ? $data_row['delete'] : false; - // $new_data_row->details = isset($data_row['details']) ? $data_row['details'] : ''; - // if ($data_row['type'] != 'relation') { - // $new_data_row->relation = null; - // } else { - // $relation = []; - // if (isset($data_row['relation_type'])) { - // $relation['relation_type'] = $data_row['relation_type']; - // } - // if (isset($data_row['destination_table'])) { - // $relation['destination_table'] = $data_row['destination_table']; - // } - // if (isset($data_row['destination_table_column'])) { - // $relation['destination_table_column'] = $data_row['destination_table_column']; - // } - // if (isset($data_row['destination_table_display_column'])) { - // $relation['destination_table_display_column'] = $data_row['destination_table_display_column']; - // } - // if (isset($data_row['destination_table_display_more_column'])) { - // $relation['destination_table_display_more_column'] = $data_row['destination_table_display_more_column']; - // } - // if (in_array(count($relation), range(4, 5))) { - // $new_data_row->relation = json_encode($relation); - // } - // } - // $new_data_row->order = $index + 1; - // $new_data_row->save(); - - // $new_data_rows[] = $new_data_row; - // } - - // if ($data_type->generate_permissions) { - // Permission::generateFor($data_type->name, true); - // } else { - // Permission::removeFrom($data_type->name); - // } - - // $this->addEditMenuItem($data_type); - - // $data_type->data_rows = $new_data_rows; - - // event(new CRUDDataUpdated($data_type, null)); - - // $this->generateAPIDocs($table_name, $data_rows, $data_type); - // DB::commit(); - - // activity('CRUD') - // ->causedBy(auth()->user() ?? null) - // ->withProperties([ - // 'old' => $data_type, - // 'new' => $request->input(), - // ]) - // ->performedOn($data_type) - // ->event('updated') - // ->log('CRUD table '.$data_type->slug.' has been updated'); - - // return ApiResponse::success($data_type); - // } catch (Exception $e) { - // DB::rollBack(); - - // return ApiResponse::failed($e); - // } - // } + public function read(Request $request) + { + try { + $request->validate([ + 'table' => 'required|exists:Uasoft\Badaso\Models\DataType,name', + ]); + + $table = $request->input('table', ''); + $data_type = Badaso::model('DataType')::where('name', $table)->first(); + $data_rows = $this->dataRowsTypeReplace($data_type->dataRows); + + $table_fields = SchemaManager::describeTable($table); + $generated_fields = collect($data_rows)->pluck('field')->toArray(); + + foreach ($table_fields as $key => $column) { + $field = $key; + $column = collect($column)->toArray(); + if (!in_array($field, $generated_fields)) { + $data_row['data_type_id'] = $data_type->id; + $data_row['field'] = $key; + $data_row['type'] = DataTypeToComponent::convert($column['type']); + $data_row['displayName'] = Str::studly($field); + $data_row['required'] = $column['notnull'] ? 1 : 0; + $data_row['browse'] = 1; + $data_row['read'] = 1; + $data_row['edit'] = 0; + $data_row['add'] = 0; + $data_row['delete'] = 0; + $data_row['details'] = '{}'; + $data_row['order'] = null; + + $data_rows[] = $data_row; + } + } + + $data_type->data_rows = $data_rows; + + $data['crud'] = collect($data_type)->toArray(); + + return ApiResponse::success($data); + } catch (Exception $e) { + return APIResponse::failed($e); + } + } + + public function readBySlug(Request $request) + { + try { + $request->validate([ + 'slug' => 'required|exists:Uasoft\Badaso\Models\DataType,slug', + ]); + + $slug = $request->input('slug', ''); + $data_type = Badaso::model('DataType')::where('slug', $slug)->first(); + $data_rows = $this->dataRowsTypeReplace($data_type->dataRows); + + $crud_data = $data_type; + $crud_data->data_rows = collect($data_rows)->toArray(); + + $data['crud_data'] = $crud_data; + + return ApiResponse::success($data); + } catch (Exception $e) { + return APIResponse::failed($e); + } + } + + public function edit(Request $request) + { + $this->addTablePolymorphism($request); + DB::beginTransaction(); + + try { + $request->validate([ + 'id' => 'required|exists:Uasoft\Badaso\Models\DataType', + 'name' => [ + 'required', + "unique:Uasoft\Badaso\Models\DataType,name,{$request->id}", + function ($attribute, $value, $fail) { + if (!Schema::hasTable($value)) { + $fail(__('badaso::validation.crud.table_not_found', ['table' => $value])); + } + }, + ], + 'rows' => 'required', + 'rows.*.field' => [ + 'required', + function ($attribute, $value, $fail) use ($request) { + if (!Schema::hasColumn($request->name, $value)) { + $split_attribute = explode('.', $attribute); + $split_attribute[2] = 'relation_type'; + $field_to_relation = join('.', $split_attribute); + if (!$field_to_relation == 'belongs_to_many') { + $request->{$attribute} == $value ? $value : $fail(__('badaso::validation.crud.table_column_not_found', ['table_column' => "$request->name.{$value}"])); + } + } else { + $table_fields = SchemaManager::describeTable($request->name); + $field = collect($table_fields)->where('field', $value)->first(); + $row = collect($request->rows)->where('field', $value)->first(); + if (!$row['add'] && !$field['autoincrement'] && $field['notnull'] && is_null($field['default'])) { + $fail(__('badaso::validation.crud.table_column_not_have_default_value', ['table_column' => "$request->name.{$value}"])); + } elseif ($row['field'] != 'id' && $field['key'] == 'PRI') { + $fail(__('badaso::validation.crud.id_table_wrong', ['table_column' => "$request->name.{$value}"])); + } + } + }, + ], + 'rows.*.type' => 'required', + 'rows.*.display_name' => 'required', + 'display_name_singular' => 'required', + 'notification.*.event' => ['in:onCreate,onRead,onUpdate,onDelete'], + 'create_soft_delete' => ['required', 'boolean', function ($att, $val, $failed) use ($request) { + if (isset($request->name) && $val) { + if (!Schema::hasColumn($request->name, 'deleted_at')) { + $failed(__('badaso::validation.crud.table_deleted_at_not_exists', [ + 'table_name' => $request->name, + ])); + } + } + }], + ]); + + $table_name = $request->input('name'); + + $data_type = DataType::find($request->input('id')); + + $data_type->name = $table_name; + $data_type->slug = $request->input('slug') ?? Str::slug($table_name); + $data_type->display_name_singular = $request->input('display_name_singular'); + $data_type->display_name_plural = $request->input('display_name_plural') ?? Str::plural($data_type->display_name_singular); + $data_type->icon = $request->input('icon'); + $data_type->model_name = $request->input('model_name'); + $data_type->policy_name = $request->input('policy_name'); + $data_type->order_column = $request->input('order_column'); + $data_type->order_display_column = $request->input('order_display_column'); + $data_type->order_direction = $request->input('order_direction'); + $data_type->description = $request->input('description'); + $data_type->generate_permissions = $request->input('generate_permissions'); + $data_type->server_side = $request->input('server_side'); + $data_type->details = $request->input('details'); + $data_type->controller = $request->input('controller'); + $data_type->notification = json_encode($request->input('notification')); + $data_type->is_soft_delete = $request->input('create_soft_delete'); + $data_type->save(); + + DataRow::where('data_type_id', $data_type->id)->delete(); + + $data_rows = $request->input('rows') ?? []; + $new_data_rows = []; + foreach ($data_rows as $index => $data_row) { + $new_data_row = new DataRow(); + $new_data_row->data_type_id = $data_type->id; + $new_data_row->field = $data_row['field']; + $new_data_row->type = $data_row['type']; + $new_data_row->display_name = $data_row['display_name']; + $new_data_row->required = isset($data_row['required']) ? $data_row['required'] : false; + $new_data_row->browse = isset($data_row['browse']) ? $data_row['browse'] : false; + $new_data_row->read = isset($data_row['read']) ? $data_row['read'] : false; + $new_data_row->edit = isset($data_row['edit']) ? $data_row['edit'] : false; + $new_data_row->add = isset($data_row['add']) ? $data_row['add'] : false; + $new_data_row->delete = isset($data_row['delete']) ? $data_row['delete'] : false; + $new_data_row->details = isset($data_row['details']) ? $data_row['details'] : ''; + if ($data_row['type'] != 'relation') { + $new_data_row->relation = null; + } else { + $relation = []; + if (isset($data_row['relation_type'])) { + $relation['relation_type'] = $data_row['relation_type']; + } + if (isset($data_row['destination_table'])) { + $relation['destination_table'] = $data_row['destination_table']; + } + if (isset($data_row['destination_table_column'])) { + $relation['destination_table_column'] = $data_row['destination_table_column']; + } + if (isset($data_row['destination_table_display_column'])) { + $relation['destination_table_display_column'] = $data_row['destination_table_display_column']; + } + if (isset($data_row['destination_table_display_more_column'])) { + $relation['destination_table_display_more_column'] = $data_row['destination_table_display_more_column']; + } + if (in_array(count($relation), range(4, 5))) { + $new_data_row->relation = json_encode($relation); + } + } + $new_data_row->order = $index + 1; + $new_data_row->save(); + + $new_data_rows[] = $new_data_row; + } + + if ($data_type->generate_permissions) { + Permission::generateFor($data_type->name, true); + } else { + Permission::removeFrom($data_type->name); + } + + $this->addEditMenuItem($data_type); + + $data_type->data_rows = $new_data_rows; + + event(new CRUDDataUpdated($data_type, null)); + + $this->generateAPIDocs($table_name, $data_rows, $data_type); + DB::commit(); + + activity('CRUD') + ->causedBy(auth()->user() ?? null) + ->withProperties([ + 'old' => $data_type, + 'new' => $request->input(), + ]) + ->performedOn($data_type) + ->event('updated') + ->log('CRUD table ' . $data_type->slug . ' has been updated'); + + return ApiResponse::success($data_type); + } catch (Exception $e) { + DB::rollBack(); + + return ApiResponse::failed($e); + } + } public function add(Request $request) { @@ -309,7 +306,7 @@ public function add(Request $request) 'required', 'unique:Uasoft\Badaso\Models\DataType', function ($attribute, $value, $fail) { - if (! Schema::hasTable($value)) { + if (!Schema::hasTable($value)) { $fail(__('badaso::validation.crud.table_not_found', ['table' => $value])); } }, @@ -319,18 +316,18 @@ function ($attribute, $value, $fail) { 'rows.*.field' => [ 'required', function ($attribute, $value, $fail) use ($request) { - if (! Schema::getColumns($request->name, $value)) { + if (!Schema::hasColumn($request->name, $value)) { $split_attribute = explode('.', $attribute); $split_attribute[2] = 'relation_type'; $field_to_relation = join('.', $split_attribute); - if (! $field_to_relation == 'belongs_to_many') { + if (!$field_to_relation == 'belongs_to_many') { $fail(__('badaso::validation.crud.table_column_not_found', ['table_column' => "$request->name.{$value}"])); } } else { $table_fields = SchemaManager::describeTable($request->name); $field = collect($table_fields)->where('field', $value)->first(); $row = collect($request->rows)->where('field', $value)->first(); - if (! $row['add'] && ! $field['autoincrement'] && $field['notnull'] && is_null($field['default'])) { + if (!$row['add'] && !$field['autoincrement'] && $field['notnull'] && is_null($field['default'])) { $fail(__('badaso::validation.crud.table_column_not_have_default_value', ['table_column' => "$request->name.{$value}"])); } elseif ($row['field'] != 'id' && $field['key'] == 'PRI') { $fail(__('badaso::validation.crud.id_table_wrong', ['table_column' => "$request->name.{$value}"])); @@ -344,7 +341,7 @@ function ($attribute, $value, $fail) use ($request) { 'notification.*.event' => ['in:onCreate,onRead,onUpdate,onDelete'], 'create_soft_delete' => ['required', 'boolean', function ($att, $val, $failed) use ($request) { if (isset($request->name) && $val) { - if (! Schema::hasColumn($request->name, 'deleted_at')) { + if (!Schema::hasColumn($request->name, 'deleted_at')) { $failed(__('badaso::validation.crud.table_deleted_at_not_exists', [ 'table_name' => $request->name, ])); @@ -432,7 +429,7 @@ function ($attribute, $value, $fail) use ($request) { ->withProperties(['attributes' => $new_data_type]) ->performedOn($new_data_type) ->event('created') - ->log('CRUD table '.$new_data_type->slug.' has been created'); + ->log('CRUD table ' . $new_data_type->slug . ' has been created'); return ApiResponse::success($new_data_type); } catch (Exception $e) { @@ -442,205 +439,205 @@ function ($attribute, $value, $fail) use ($request) { } } - // public function delete(Request $request) - // { - // DB::beginTransaction(); - - // try { - // $request->validate([ - // 'id' => 'required|exists:Uasoft\Badaso\Models\DataType,id', - // ]); - - // $data_type = DataType::find($request->id); - - // $this->deleteAPIDocs($data_type->name); - - // Permission::removeFrom($data_type->name); - - // $this->deleteMenuItem($data_type); - - // $data_type->delete(); - - // event(new CRUDDataDeleted($data_type)); - - // DB::commit(); - - // activity('CRUD') - // ->causedBy(auth()->user() ?? null) - // ->withProperties(['attributes' => $data_type]) - // ->performedOn($data_type) - // ->event('deleted') - // ->log('CRUD table '.$data_type->slug.' has been deleted'); - - // return ApiResponse::success(); - // } catch (Exception $e) { - // DB::rollBack(); - - // return ApiResponse::failed($e); - // } - // } - - // private function addEditMenuItem($data_type) - // { - // $menu_key = config('badaso.default_menu'); - // $menu = Menu::where('key', $menu_key)->first(); - // $url = '/'.$menu_key.'/'.$data_type->slug; - - // if (is_null($menu)) { - // $menu = new Menu(); - // $menu->key = $menu_key; - // $menu->display_name = Str::studly($menu_key); - // $menu->save(); - // } - - // $menu_item = MenuItem::firstOrNew([ - // 'menu_id' => $menu->id, - // 'url' => $url, - // ]); - - // $menu_item = MenuItem::where('menu_id', $menu->id)->where('url', $url)->first(); - // if ($menu_item) { - // $menu_item->title = $data_type->display_name_plural; - // $menu_item->target = '_self'; - // $menu_item->icon_class = $data_type->icon; - // $menu_item->color = null; - // $menu_item->parent_id = null; - // $menu_item->permissions = $data_type->generate_permissions ? 'browse_'.$data_type->name : null; - // $menu_item->save(); - // } else { - // $menu_item = new MenuItem(); - // $menu_item->menu_id = $menu->id; - // $menu_item->url = $url; - // $menu_item->title = $data_type->display_name_plural; - // $menu_item->target = '_self'; - // $menu_item->icon_class = $data_type->icon; - // $menu_item->color = null; - // $menu_item->parent_id = null; - // $menu_item->permissions = $data_type->generate_permissions ? 'browse_'.$data_type->name : null; - // $menu_item->order = $menu_item->highestOrderMenuItem(); - // $menu_item->save(); - // } - // } - - // private function deleteMenuItem($data_type) - // { - // $menu_key = config('badaso.default_menu'); - // $url = '/'.$menu_key.'/'.$data_type->slug; - // MenuItem::where('url', $url)->delete(); - // } - - // private function generateAPIDocs($table_name, $data_rows, $data_type) - // { - // $filesystem = new LaravelFileSystem(); - // $file_path = ApiDocs::getFilePath($table_name); - // $stub = ApiDocs::getStub($table_name, $data_rows, $data_type); - // if (! $filesystem->put($file_path, $stub)) { - // return false; - // } - - // return true; - // } - - // private function deleteAPIDocs($table_name) - // { - // $filesystem = new LaravelFileSystem(); - // $file_path = ApiDocs::getFilePath($table_name); - // if ($filesystem->exists($file_path)) { - // return $filesystem->delete($file_path); - // } - - // return false; - // } - - // private function addTablePolymorphism($request) - // { - // foreach ($request['rows'] as $key => $value) { - // if (isset($value['relation_type']) && $value['relation_type'] == 'belongs_to_many') { - // $table = $value['field']; - // $rows = [ - // 0 => [ - // 'id' => 'id', - // 'field_name' => 'id', - // 'field_type' => 'bigint', - // 'field_length' => null, - // 'field_null' => false, - // 'field_attribute' => true, - // 'field_increment' => true, - // 'field_index' => 'primary', - // 'field_default' => null, - // 'undeletable' => true, - // ], - // 1 => [ - // 'id' => $request['name'].'_id', - // 'field_name' => $request['name'].'_id', - // 'field_type' => 'bigint', - // 'field_length' => null, - // 'field_null' => false, - // 'field_attribute' => true, - // 'field_increment' => false, - // 'field_index' => 'foreign', - // 'field_default' => null, - // ], - // 2 => [ - // 'id' => $value['destination_table'].'_id', - // 'field_name' => $value['destination_table'].'_id', - // 'field_type' => 'bigint', - // 'field_length' => null, - // 'field_null' => false, - // 'field_attribute' => true, - // 'field_increment' => false, - // 'field_index' => 'foreign', - // 'field_default' => null, - // ], - // 3 => [ - // 'field_name' => 'created_at', - // 'field_type' => 'timestamp', - // 'field_length' => null, - // 'field_null' => true, - // 'field_attribute' => false, - // 'field_increment' => false, - // 'field_index' => null, - // 'field_default' => null, - // 'undeletable' => true, - // 'indexes' => true, - // ], - // 4 => [ - // 'field_name' => 'updated_at', - // 'field_type' => 'timestamp', - // 'field_length' => null, - // 'field_null' => true, - // 'field_attribute' => false, - // 'field_increment' => false, - // 'field_index' => null, - // 'field_default' => null, - // 'undeletable' => true, - // ], - // ]; - - // $relations = [ - // $request['name'].'_id' => [ - // 'source_field' => $request['name'].'_id', - // 'target_table' => $request['name'], - // 'target_field' => 'id', - // 'on_delete' => 'cascade', - // 'on_update' => 'restrict', - // ], - // $value['destination_table'].'_id' => [ - // 'source_field' => $value['destination_table'].'_id', - // 'target_table' => $value['destination_table'], - // 'target_field' => 'id', - // 'on_delete' => 'cascade', - // 'on_update' => 'restrict', - // ], - // ]; - // if (! Schema::hasTable($table)) { - // $this->file_name = $this->file_generator->generateBDOMigrationFile($table, 'create', $rows, $relations); - // $exitCode = Artisan::call('migrate', [ - // '--path' => 'database/migrations/badaso/', - // '--force' => true, - // ]); - // } - // } - // } - // } + public function delete(Request $request) + { + DB::beginTransaction(); + + try { + $request->validate([ + 'id' => 'required|exists:Uasoft\Badaso\Models\DataType,id', + ]); + + $data_type = DataType::find($request->id); + + $this->deleteAPIDocs($data_type->name); + + Permission::removeFrom($data_type->name); + + $this->deleteMenuItem($data_type); + + $data_type->delete(); + + event(new CRUDDataDeleted($data_type)); + + DB::commit(); + + activity('CRUD') + ->causedBy(auth()->user() ?? null) + ->withProperties(['attributes' => $data_type]) + ->performedOn($data_type) + ->event('deleted') + ->log('CRUD table ' . $data_type->slug . ' has been deleted'); + + return ApiResponse::success(); + } catch (Exception $e) { + DB::rollBack(); + + return ApiResponse::failed($e); + } + } + + private function addEditMenuItem($data_type) + { + $menu_key = config('badaso.default_menu'); + $menu = Menu::where('key', $menu_key)->first(); + $url = '/' . $menu_key . '/' . $data_type->slug; + + if (is_null($menu)) { + $menu = new Menu(); + $menu->key = $menu_key; + $menu->display_name = Str::studly($menu_key); + $menu->save(); + } + + $menu_item = MenuItem::firstOrNew([ + 'menu_id' => $menu->id, + 'url' => $url, + ]); + + $menu_item = MenuItem::where('menu_id', $menu->id)->where('url', $url)->first(); + if ($menu_item) { + $menu_item->title = $data_type->display_name_plural; + $menu_item->target = '_self'; + $menu_item->icon_class = $data_type->icon; + $menu_item->color = null; + $menu_item->parent_id = null; + $menu_item->permissions = $data_type->generate_permissions ? 'browse_' . $data_type->name : null; + $menu_item->save(); + } else { + $menu_item = new MenuItem(); + $menu_item->menu_id = $menu->id; + $menu_item->url = $url; + $menu_item->title = $data_type->display_name_plural; + $menu_item->target = '_self'; + $menu_item->icon_class = $data_type->icon; + $menu_item->color = null; + $menu_item->parent_id = null; + $menu_item->permissions = $data_type->generate_permissions ? 'browse_' . $data_type->name : null; + $menu_item->order = $menu_item->highestOrderMenuItem(); + $menu_item->save(); + } + } + + private function deleteMenuItem($data_type) + { + $menu_key = config('badaso.default_menu'); + $url = '/' . $menu_key . '/' . $data_type->slug; + MenuItem::where('url', $url)->delete(); + } + + private function generateAPIDocs($table_name, $data_rows, $data_type) + { + $filesystem = new LaravelFileSystem(); + $file_path = ApiDocs::getFilePath($table_name); + $stub = ApiDocs::getStub($table_name, $data_rows, $data_type); + if (!$filesystem->put($file_path, $stub)) { + return false; + } + + return true; + } + + private function deleteAPIDocs($table_name) + { + $filesystem = new LaravelFileSystem(); + $file_path = ApiDocs::getFilePath($table_name); + if ($filesystem->exists($file_path)) { + return $filesystem->delete($file_path); + } + + return false; + } + + private function addTablePolymorphism($request) + { + foreach ($request['rows'] as $key => $value) { + if (isset($value['relation_type']) && $value['relation_type'] == 'belongs_to_many') { + $table = $value['field']; + $rows = [ + 0 => [ + 'id' => 'id', + 'field_name' => 'id', + 'field_type' => 'bigint', + 'field_length' => null, + 'field_null' => false, + 'field_attribute' => true, + 'field_increment' => true, + 'field_index' => 'primary', + 'field_default' => null, + 'undeletable' => true, + ], + 1 => [ + 'id' => $request['name'] . '_id', + 'field_name' => $request['name'] . '_id', + 'field_type' => 'bigint', + 'field_length' => null, + 'field_null' => false, + 'field_attribute' => true, + 'field_increment' => false, + 'field_index' => 'foreign', + 'field_default' => null, + ], + 2 => [ + 'id' => $value['destination_table'] . '_id', + 'field_name' => $value['destination_table'] . '_id', + 'field_type' => 'bigint', + 'field_length' => null, + 'field_null' => false, + 'field_attribute' => true, + 'field_increment' => false, + 'field_index' => 'foreign', + 'field_default' => null, + ], + 3 => [ + 'field_name' => 'created_at', + 'field_type' => 'timestamp', + 'field_length' => null, + 'field_null' => true, + 'field_attribute' => false, + 'field_increment' => false, + 'field_index' => null, + 'field_default' => null, + 'undeletable' => true, + 'indexes' => true, + ], + 4 => [ + 'field_name' => 'updated_at', + 'field_type' => 'timestamp', + 'field_length' => null, + 'field_null' => true, + 'field_attribute' => false, + 'field_increment' => false, + 'field_index' => null, + 'field_default' => null, + 'undeletable' => true, + ], + ]; + + $relations = [ + $request['name'] . '_id' => [ + 'source_field' => $request['name'] . '_id', + 'target_table' => $request['name'], + 'target_field' => 'id', + 'on_delete' => 'cascade', + 'on_update' => 'restrict', + ], + $value['destination_table'] . '_id' => [ + 'source_field' => $value['destination_table'] . '_id', + 'target_table' => $value['destination_table'], + 'target_field' => 'id', + 'on_delete' => 'cascade', + 'on_update' => 'restrict', + ], + ]; + if (!Schema::hasTable($table)) { + $this->file_name = $this->file_generator->generateBDOMigrationFile($table, 'create', $rows, $relations); + $exitCode = Artisan::call('migrate', [ + '--path' => 'database/migrations/badaso/', + '--force' => true, + ]); + } + } + } + } } diff --git a/src/Controllers/BadasoDatabaseController.php b/src/Controllers/BadasoDatabaseController.php index ee1d12ef..6cbff66c 100644 --- a/src/Controllers/BadasoDatabaseController.php +++ b/src/Controllers/BadasoDatabaseController.php @@ -109,7 +109,6 @@ function ($attribute, $value, $fail) { Rule::notIn(Badaso::getProtectedTables()), ], ]); - $columns = SchemaManager::describeTable($request->table)->toArray(); $columnsFK = SchemaManager::getDoctrineForeignKeys($request->table); $fKConstraints = []; diff --git a/src/Controllers/BadasoTableController.php b/src/Controllers/BadasoTableController.php index 8088792c..374a25f4 100644 --- a/src/Controllers/BadasoTableController.php +++ b/src/Controllers/BadasoTableController.php @@ -22,13 +22,12 @@ class BadasoTableController extends Controller public function browse(Request $request) { try { - // $tables = SchemaManager::listTables(); - $tables = Schema::getTables(); + $tables = SchemaManager::listTables(); $custom_list = []; foreach ($tables as $key => $value) { $table = []; - $table['value'] = $value["name"]; - $table['label'] = ucfirst(str_replace('_', ' ', $value["name"])); + $table['value'] = $key; + $table['label'] = ucfirst(str_replace('_', ' ', $key)); $custom_list[] = $table; } diff --git a/src/Database/Schema/SchemaManager.php b/src/Database/Schema/SchemaManager.php index 519da72f..2bc4b4e4 100644 --- a/src/Database/Schema/SchemaManager.php +++ b/src/Database/Schema/SchemaManager.php @@ -2,17 +2,30 @@ namespace Uasoft\Badaso\Database\Schema; -use Doctrine\DBAL\Schema\Table; -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; +use Doctrine\DBAL\Schema\SchemaException; +use Doctrine\DBAL\Schema\Table as DoctrineTable; +use Illuminate\Support\Facades\DB; use Uasoft\Badaso\Database\Types\Type; +use Doctrine\DBAL\DriverManager; abstract class SchemaManager { + // todo: trim parameters + public static function __callStatic($method, $args) { - return Schema::$method(...$args); + return static::manager()->$method(...$args); + } + + public static function manager() + { + return DB::connection()->select('SELECT schema_name FROM information_schema.schemata'); + } + + public static function getDatabaseConnection() + { + return DB::connection()->getDoctrineConnection(); } public static function tableExists($table) @@ -21,52 +34,84 @@ public static function tableExists($table) $table = [$table]; } - foreach ($table as $tbl) { - if (!Schema::hasTable($tbl)) { - return false; - } - } - - return true; + return static::manager()->tablesExist($table); } public static function listTables() { - $tables = DB::select('SHOW TABLES'); - $database_name = DB::getDatabaseName(); - $tables_key = "Tables_in_$database_name"; - - $result = []; - foreach ($tables as $table) { - $table_name = $table->$tables_key; - $result[$table_name] = static::listTableDetails($table_name); + // $sm = static::registerConnection()->createSchemaManager(); + // $list_tables = $sm->listTables(); + + $sm = Schema::getTables(); + + $tables = []; + + foreach ($sm as $key => $table_name) { + // $tables[$table_name["name"]] = static::listTableDetails($table_name["name"]); + $tables[$table_name["name"]] = $table_name["name"]; } - - return $result; + + return $tables; } + /** + * @param string $table_name + * @return \Uasoft\Badaso\Database\Schema\Table + */ public static function listTableDetails($table_name) { - $columns = Schema::getColumnListing($table_name); + $sm =static::registerConnection()->createSchemaManager(); + $columns = $sm->listTableColumns($table_name); + + $foreign_keys = []; + if (static::registerConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) { + $foreign_keys = $sm->listTableForeignKeys($table_name); + } - // $foreign_keys = static::listTableForeignKeys($table_name); - $foreign_keys[] = Schema::getForeignKeys($table_name); - // $indexes = Schema::listTableIndexes($table_name); - $indexes[] = Schema::getIndexes($table_name); - return new Table($table_name, $columns, $indexes, $foreign_keys, []); + $indexes = $sm->listTableIndexes($table_name); + + return new Table($table_name, $columns, $indexes, [],$foreign_keys, []); } - public static function getColumnDetails($table_name, $column_name) + public static function registerConnection() { - return DB::select(DB::raw("SHOW COLUMNS FROM `$table_name` LIKE '$column_name'"))[0]; + $databaseConfig = config('database.connections.' . config('database.default')); + $driver_name = DB::getDriverName(); + if($driver_name == 'mysql' || $driver_name = 'pgsql') { + $connectionParams = [ + 'dbname' => $databaseConfig['database'], + 'user' => $databaseConfig['username'], + 'password' => $databaseConfig['password'], + 'host' => $databaseConfig['host'], + 'driver' => 'pdo_' . $driver_name, + 'port' => $databaseConfig['port'], + ]; + } else { + $connectionParams = [ + 'user' => $databaseConfig['username'], + 'password' => $databaseConfig['password'], + 'path' => $databaseConfig['database'], + 'driver' => 'pdo_' . $driver_name, + ]; + } + + $doctrine_connection = DriverManager::getConnection($connectionParams); + + return $doctrine_connection; } + /** + * Describes given table. + * + * @param string $table_name + * @return \Illuminate\Support\Collection + */ public static function describeTable($table_name) { - // Type::registerCustomPlatformTypes(); + Type::registerCustomPlatformTypes(); $table = static::listTableDetails($table_name); - + return collect($table->columns)->map(function ($column) use ($table) { $column_array = Column::toArray($column); @@ -96,32 +141,22 @@ public static function listTableColumnNames($table_name) { Type::registerCustomPlatformTypes(); - return Schema::getColumnListing($table_name); + $column_names = []; + + foreach (static::manager()->listTableColumns($table_name) as $column) { + $column_names[] = $column->getName(); + } + + return $column_names; } public static function createTable($table) { - if (!($table instanceof Blueprint)) { + if (!($table instanceof DoctrineTable)) { $table = Table::make($table); } - Schema::create($table->getTable(), function (Blueprint $blueprint) use ($table) { - foreach ($table->getColumns() as $column) { - $blueprint->addColumn($column->getType(), $column->getName(), $column->getOptions()); - } - - foreach ($table->getIndexes() as $index) { - $blueprint->index($index->getColumns(), $index->getName(), $index->getOptions()); - } - - foreach ($table->getForeignKeys() as $foreignKey) { - $blueprint->foreign($foreignKey->getLocalColumns()) - ->references($foreignKey->getForeignColumns()) - ->on($foreignKey->getForeignTable()) - ->onDelete($foreignKey->onDelete()) - ->onUpdate($foreignKey->onUpdate()); - } - }); + static::manager()->createTable($table); } public static function getDoctrineTable($table) @@ -129,26 +164,20 @@ public static function getDoctrineTable($table) $table = trim($table); if (!static::tableExists($table)) { - throw new \Exception("Table $table does not exist."); + throw SchemaException::tableDoesNotExist($table); } - return static::listTableDetails($table); + return static::manager()->listTableDetails($table); } public static function getDoctrineColumn($table, $column) { - return static::getColumnDetails($table, $column); - } - - public static function listTableForeignKeys($table_name) - { - $foreignKeys = DB::select(DB::raw("SELECT * FROM information_schema.key_column_usage WHERE TABLE_NAME = '$table_name' AND TABLE_SCHEMA = '" . DB::getDatabaseName() . "' AND REFERENCED_COLUMN_NAME IS NOT NULL")); - return $foreignKeys; + return static::getDoctrineTable($table)->getColumn($column); } - public static function listTableIndexes($table_name) + public static function getDoctrineForeignKeys($table) { - $indexes = DB::select(DB::raw("SHOW INDEX FROM `$table_name`")); - return $indexes; + $sm = static::registerConnection()->createSchemaManager(); + return $sm->listTableForeignKeys($table); } } diff --git a/src/Database/Types/Type.php b/src/Database/Types/Type.php index 5fe72aa0..b973ebff 100644 --- a/src/Database/Types/Type.php +++ b/src/Database/Types/Type.php @@ -2,10 +2,12 @@ namespace Uasoft\Badaso\Database\Types; -use Illuminate\Support\Facades\DB; -use Uasoft\Badaso\Database\Platforms\Platform; -use Doctrine\DBAL\Types\Type as DoctrineType; use Doctrine\DBAL\Platforms\AbstractPlatform as DoctrineAbstractPlatform; +use Doctrine\DBAL\Types\Type as DoctrineType; +use Uasoft\Badaso\Database\Platforms\Platform; +use Uasoft\Badaso\Database\Schema\SchemaManager; +use Illuminate\Support\Facades\DB; +use Doctrine\DBAL\DriverManager; abstract class Type extends DoctrineType { @@ -15,7 +17,6 @@ abstract class Type extends DoctrineType protected static $platform_types = []; protected static $custom_type_options = []; protected static $type_categories = []; - protected static $types = []; const NAME = 'UNDEFINED_TYPE_NAME'; const NOT_SUPPORTED = 'notSupported'; @@ -30,7 +31,7 @@ public function getName() return static::NAME; } - public static function toArray($type) + public static function toArray(DoctrineType $type) { $custom_type_options = $type->customOptions ?? []; @@ -49,11 +50,13 @@ public static function getPlatformTypes() static::registerCustomPlatformTypes(); } + $doctrine_connection = SchemaManager::registerConnection(); + $platform = $doctrine_connection->getDatabasePlatform(); $platform_name = DB::getDriverName(); static::$platform_types = Platform::getPlatformTypes( $platform_name, - static::getPlatformTypeMapping($platform_name) + static::getPlatformTypeMapping($platform) ); static::$platform_types = static::$platform_types->map(function ($type) { @@ -63,15 +66,14 @@ public static function getPlatformTypes() return static::$platform_types; } - public static function getPlatformTypeMapping(DoctrineAbstractPlatform $platform_name) + public static function getPlatformTypeMapping(DoctrineAbstractPlatform $platform) { if (static::$platform_type_mapping) { return static::$platform_type_mapping; } - // Anda perlu mendefinisikan cara mengambil pemetaan tipe khusus untuk platform tertentu static::$platform_type_mapping = collect( - get_protected_property($platform_name, 'doctrineTypeMapping') + get_protected_property($platform, 'doctrineTypeMapping') ); return static::$platform_type_mapping; @@ -83,25 +85,27 @@ public static function registerCustomPlatformTypes($force = false) return; } - $platform_name = DB::getDriverName(); - + $doctrine_connection = SchemaManager::registerConnection(); + $platform = $doctrine_connection->getDatabasePlatform(); + $platform_name = ucfirst(DB::getDriverName()); + $custom_types = array_merge( static::getPlatformCustomTypes('Common'), static::getPlatformCustomTypes($platform_name) ); - + foreach ($custom_types as $type) { $name = $type::NAME; - if (!static::hasType($name)) { - static::addType($name, $type); - } else { + if (static::hasType($name)) { static::overrideType($name, $type); + } else { + static::addType($name, $type); } $db_type = defined("{$type}::DBTYPE") ? $type::DBTYPE : $name; - - static::registerDoctrineTypeMapping($db_type, $name); + + $platform->registerDoctrineTypeMapping($db_type, $name); } static::addCustomTypeOptions($platform_name); @@ -109,29 +113,6 @@ public static function registerCustomPlatformTypes($force = false) static::$custom_type_registered = true; } - protected static function registerDoctrineTypeMapping($db_type, $name) - { - $databaseConfig = config('database.connections.' . config('database.default')); - - $connectionParams = [ - 'dbname' => $databaseConfig['database'], - 'user' => $databaseConfig['username'], - 'password' => $databaseConfig['password'], - 'host' => $databaseConfig['host'], - 'driver' => 'pdo_mysql', // Sesuaikan dengan driver yang digunakan, misal: 'pdo_pgsql' untuk PostgreSQL - 'port' => $databaseConfig['port'], - ]; - - $doctrine_connection = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); - $platform = $doctrine_connection->getDatabasePlatform(); - - if ($platform->hasDoctrineTypeMappingFor($db_type)) { - $platform->registerDoctrineTypeMapping($db_type, $name); - } else { - throw new \Doctrine\DBAL\Exception("Type to be overwritten $db_type does not exist."); - } - } - protected static function addCustomTypeOptions($platform_name) { static::registerCommonCustomTypeOptions(); @@ -354,24 +335,4 @@ public static function getTypeCategories() return static::$type_categories; } - - public static function hasType($name) - { - return DoctrineType::hasType($name); - } - - public static function getType($name) - { - return static::$types[$name] ?? null; - } - - public static function addType($name, $type) - { - static::$types[$name] = new $type(); - } - - public static function overrideType($name, $type) - { - static::$types[$name] = new $type(); - } }