tables()->where('name', $table)->first(); $revision = $tableModel->revision; return view('table.view', [ 'table' => $tableModel, 'revision' => $revision, 'columns' => Column::columnsFromJson(json_decode($revision->columns)), 'rows' => $revision->rows, ]); } /** * SHow a form for creating a new table * * @return \Illuminate\Http\Response */ public function create() { $exampleColumns = "latin,string,Latin Name\n" . "common,string,Common Name\n" . "lifespan,int,Lifespan (years)"; $exampleData = "Mercenaria mercenaria,hard clam,40\n" . "Magallana gigas,pacific oyster,30\n" . "Patella vulgata,common limpet,20"; return view('table.create', compact('exampleColumns', 'exampleData') ); } public function storeNew(Request $request) { /** @var User $u */ $u = \Auth::user(); $this->validate($request, [ 'name' => 'required|string|max:255', 'title' => 'string|string|max:255', 'description' => 'string|nullable|max:4000', 'license' => 'string|nullable|max:4000', 'origin' => 'string|nullable|max:4000', 'columns' => 'required|string', 'data' => 'string|nullable', ]); // Check if table name is unique for user $tabName = $request->get('name'); if ($u->tables()->where('name', $tabName)->exists()) { return $this->backWithErrors([ 'name' => "A table called \"$tabName\" already exists in your account.", ]); } // Parse and validate the columns specification /** @var Column[] $columns */ $columns = []; $column_keys = []; // for checking duplicates $colTable = array_map('str_getcsv', explode("\n", $request->get('columns'))); // prevent griefing via long list of columns if (count($colTable) > 100) return $this->backWithErrors(['columns' => "Too many columns"]); foreach ($colTable as $col) { $col = array_map('trim', $col); if (count($col) < 2 || strlen($col[0])==0) { return $this->backWithErrors(['columns' => "All columns must have at least name and type."]); } try { if (in_array($col[0], $column_keys)) { return $this->backWithErrors(['columns' => "Duplicate column: $col[0]"]); } $column_keys[] = $col[0]; $columns[] = new Column([ 'name' => $col[0], 'type' => $col[1], 'title' => count($col) >= 3 ? $col[2] : $col[0], // title falls back to =name if not specified, ]); } catch (\Exception $e) { return $this->backWithErrors(['columns' => $e->getMessage()]); } } if (count($columns) == 0) return $this->backWithErrors(['columns' => "Define at least one column"]); $rowTable = array_map('str_getcsv', explode("\n", $request->get('data'))); // Preparing data to insert into the Rows table $rowsData = null; try { $rowsData = array_map(function ($row) use ($columns) { if (count($row) != count($columns)) { throw new NotApplicableException("All rows must have " . count($columns) . " fields."); } $parsed = []; foreach ($row as $i => $val) { $key = $columns[$i]->name; $parsed[$key] = $columns[$i]->cast($val); } return [ 'data' => json_encode($parsed), ]; }, $rowTable); } catch (\Exception $e) { return $this->backWithErrors(['columns' => $e->getMessage()]); } $revisionFields = [ 'note' => "Initial revision of table $u->name/$tabName", 'columns' => json_encode($columns), 'row_count' => count($rowsData), ]; $tableFields = [ 'owner_id' => $u->id, 'revision_id' => 0, 'name' => $tabName, 'title' => $request->get('title'), 'description' => $request->get('description'), 'license' => $request->get('license'), 'origin' => $request->get('origin'), ]; \DB::transaction(function () use ($revisionFields, $tableFields, $rowsData) { $revision = Revision::create($revisionFields); $tableFields['revision_id'] = $revision->id; // to meet the not-null constraint $table = Table::create($tableFields); // Attach the revision to the table, set as current $table->revisions()->attach($revision); $table->revision()->associate($revision); // Spawn rows, linked to the revision $revision->rows()->createMany($rowsData); }); return redirect(route('table.view', ['user' => $u, 'table' => $tabName])); } }