datatable.directory codebase
				https://datatable.directory/
			
			
		
			Você não pode selecionar mais de 25 tópicos
			Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
		
		
		
		
		
			
		
			
				
					
					
						
							370 linhas
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							370 linhas
						
					
					
						
							12 KiB
						
					
					
				| <?php
 | |
| 
 | |
| 
 | |
| namespace App\Http\Controllers;
 | |
| 
 | |
| use App\Models\Proposal;
 | |
| use App\Models\Table;
 | |
| use App\Models\User;
 | |
| use App\Tables\Changeset;
 | |
| use Illuminate\Http\Request;
 | |
| use Illuminate\Support\Facades\Input;
 | |
| use MightyPork\Exceptions\SimpleValidationException;
 | |
| use MightyPork\Utils\Utils;
 | |
| 
 | |
| /**
 | |
|  * Draft composing
 | |
|  */
 | |
| class TableEditController extends Controller
 | |
| {
 | |
|     /**
 | |
|      * Initialize the session-stored changeset, if not set yet
 | |
|      *
 | |
|      * @param Table $table
 | |
|      * @return Changeset
 | |
|      */
 | |
|     private function getChangeset(Table $table)
 | |
|     {
 | |
|         if (Input::has('reset')) {
 | |
|             session()->forget($table->draftSessionKey);
 | |
|         }
 | |
| 
 | |
|         /** @var Changeset $changeset */
 | |
|         return session()->remember($table->draftSessionKey, function () use ($table) {
 | |
|             $changeset = new Changeset();
 | |
|             $changeset->table = $table;
 | |
|             $changeset->revision = $table->revision;
 | |
|             return $changeset;
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Store the changeset to session
 | |
|      *
 | |
|      * @param Changeset $changeset
 | |
|      */
 | |
|     private function storeChangeset(Changeset $changeset)
 | |
|     {
 | |
|         session()->put($changeset->table->draftSessionKey, $changeset);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Discard draft and redirect to table view
 | |
|      */
 | |
|     public function discard(User $user, string $table)
 | |
|     {
 | |
|         /** @var Table $tableModel */
 | |
|         $tableModel = $user->tables()->where('name', $table)->first();
 | |
|         if ($tableModel === null) abort(404, "No such table.");
 | |
| 
 | |
|         session()->forget($tableModel->draftSessionKey);
 | |
| 
 | |
|         return redirect($tableModel->draftRoute);
 | |
|     }
 | |
| 
 | |
|     #region Draft tabs
 | |
| 
 | |
|     /**
 | |
|      * Show the table edit view with tabs
 | |
|      *
 | |
|      * @param User $user - table owner
 | |
|      * @param string $table - table name
 | |
|      * @param string|null $tab - page tab name, kebab-case
 | |
|      * @return \Illuminate\View\View;
 | |
|      */
 | |
|     public function draft(User $user, string $table, $tab = null)
 | |
|     {
 | |
|         /** @var Table $tableModel */
 | |
|         $tableModel = $user->tables()->where('name', $table)->first();
 | |
|         if ($tableModel === null) abort(404, "No such table.");
 | |
| 
 | |
|         if ($tab == null) $tab = 'edit-rows';
 | |
| 
 | |
|         $method = camel_case('tab-'.$tab);
 | |
|         if (!method_exists($this, $method)) abort(404, "No such tab: $tab");
 | |
| 
 | |
|         $changeset = $this->getChangeset($tableModel);
 | |
| 
 | |
|         if (Input::has('dump')) {
 | |
|             dd($changeset);
 | |
|         }
 | |
| 
 | |
|         return $this->$method($changeset);
 | |
|     }
 | |
| 
 | |
|     /** @noinspection PhpUnusedPrivateMethodInspection */
 | |
|     private function tabEditRows(Changeset $changeset)
 | |
|     {
 | |
|         $revision = $changeset->revision;
 | |
|         $columns = $changeset->fetchAndTransformColumns();
 | |
|         $rows = $revision->rowsData($columns, true, false)
 | |
|             ->sortByCol($changeset->fetchRevisionColumns()[0])
 | |
|             ->paginate(25, []);
 | |
| 
 | |
|         return view('table.propose.edit-rows', [
 | |
|             'changeset' => $changeset,
 | |
|             'table' => $changeset->table,
 | |
|             'columns' => collect($columns),
 | |
|             'rows' => $rows,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     /** @noinspection PhpUnusedPrivateMethodInspection */
 | |
|     private function tabAddRows(Changeset $changeset)
 | |
|     {
 | |
|         $columns = $changeset->fetchAndTransformColumns();
 | |
|         $rows = $changeset->getAddedRows(25);
 | |
| 
 | |
|         return view('table.propose.add-rows', [
 | |
|             'changeset' => $changeset,
 | |
|             'table' => $changeset->table,
 | |
|             'columns' => collect($columns),
 | |
|             'rows' => $rows,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     /** @noinspection PhpUnusedPrivateMethodInspection */
 | |
|     private function tabAddRowsCsv(Changeset $changeset)
 | |
|     {
 | |
|         $columns = $changeset->fetchAndTransformColumns();
 | |
| 
 | |
|         return view('table.propose.add-rows-csv', [
 | |
|             'changeset' => $changeset,
 | |
|             'table' => $changeset->table,
 | |
|             'columns' => collect($columns)->where('toRemove', false),
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     /** @noinspection PhpUnusedPrivateMethodInspection */
 | |
|     private function tabManageColumns(Changeset $changeset)
 | |
|     {
 | |
|         $columns = $changeset->fetchAndTransformColumns();
 | |
| 
 | |
|         return view('table.propose.manage-columns', [
 | |
|             'changeset' => $changeset,
 | |
|             'table' => $changeset->table,
 | |
|             'columns' => collect($columns),
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     /** @noinspection PhpUnusedPrivateMethodInspection */
 | |
|     private function tabReview(Changeset $changeset)
 | |
|     {
 | |
|         return view('table.propose.review', [
 | |
|             'changeset' => $changeset,
 | |
|             'table' => $changeset->table,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     #endregion
 | |
| 
 | |
|     /**
 | |
|      * API hook called by AJAX or via forms.
 | |
|      * Generally applies modifications to the Changeset stored in session.
 | |
|      *
 | |
|      * @param Request $request
 | |
|      * @param User $user
 | |
|      * @param string $table
 | |
|      * @return \Symfony\Component\HttpFoundation\Response
 | |
|      */
 | |
|     public function draftUpdate(Request $request, User $user, string $table)
 | |
|     {
 | |
|         /** @var Table $tableModel */
 | |
|         $tableModel = $user->tables()->where('name', $table)->first();
 | |
|         if ($tableModel === null) abort(404, "No such table.");
 | |
| 
 | |
|         $changeset = $this->getChangeset($tableModel);
 | |
| 
 | |
|         $input = objBag($request->all(), false);
 | |
| 
 | |
|         $resp = null;
 | |
|         $code = 200;
 | |
| 
 | |
|         try {
 | |
|             switch ($input->action) {
 | |
|                 case 'row.update':
 | |
|                     $data = (object)$input->data;
 | |
|                     $resp = $changeset->rowUpdate($data);
 | |
|                     break;
 | |
| 
 | |
|                 case 'row.update-many':
 | |
|                     $newVals = $input->data;
 | |
|                     $updated = [];
 | |
|                     foreach ($newVals as $rowUpdate) {
 | |
|                         $r = $changeset->rowUpdate($rowUpdate);
 | |
|                         $updated[$r->_id] = $r;
 | |
|                     }
 | |
|                     $resp = $updated;
 | |
|                     break;
 | |
| 
 | |
|                 case 'row.add-csv':
 | |
|                     $fname = 'csv-file';
 | |
|                     if ($request->hasFile($fname)) {
 | |
|                         try {
 | |
|                             $file = $request->file($fname);
 | |
|                             if ($file->isValid() && $file->isReadable()) {
 | |
|                                 $handle = $file->openFile();
 | |
|                                 $csv = Utils::csvToArray($handle);
 | |
|                                 if (empty($csv)) throw new \Exception("Failed to parse CSV file.");
 | |
| 
 | |
|                                 $changeset->addFilledRows($csv);
 | |
|                                 $handle = null;
 | |
|                             } else {
 | |
|                                 throw new \Exception("File not valid.");
 | |
|                             }
 | |
|                         } catch (\Exception $e) {
 | |
|                             return $this->backWithErrors(['csv-file' => $e->getMessage()]);
 | |
|                         }
 | |
|                     }
 | |
|                     else {
 | |
|                         try {
 | |
|                             $text = trim($input->data);
 | |
|                             if (empty($text)) throw new \Exception("Empty CSV field and no file uploaded.");
 | |
|                             $changeset->addFilledRows(Utils::csvToArray($text));
 | |
|                         } catch (\Exception $e) {
 | |
|                             return $this->backWithErrors(['data' => $e->getMessage()]);
 | |
|                         }
 | |
|                     }
 | |
|                     break;
 | |
| 
 | |
|                 case 'row.remove':
 | |
|                     $isNew = $changeset->isNewRow($input->id);
 | |
|                     $changeset->rowRemove($input->id);
 | |
|                     $resp = $isNew ? null : $changeset->fetchAndTransformRow($input->id);
 | |
|                     break;
 | |
| 
 | |
|                 case 'row.remove-empty-new':
 | |
|                     $changeset->removeEmptyNewRows();
 | |
|                     break;
 | |
| 
 | |
|                 case 'row.restore':
 | |
|                     $changeset->rowRestore($input->id);
 | |
|                     $resp = $changeset->fetchAndTransformRow($input->id);
 | |
|                     break;
 | |
| 
 | |
|                 case 'rows.add':
 | |
|                     $changeset->addBlankRows($input->count);
 | |
|                     break;
 | |
| 
 | |
|                 case 'col.update':
 | |
|                     $data = (object)$input->data;
 | |
|                     $resp = $changeset->columnUpdate($data);
 | |
|                     break;
 | |
| 
 | |
|                 case 'col.remove':
 | |
|                     $isNew = $changeset->isNewColumn($input->id);
 | |
|                     $changeset->columnRemove($input->id);
 | |
|                     $resp = $isNew ? null : $changeset->fetchAndTransformColumn($input->id);
 | |
|                     break;
 | |
| 
 | |
|                 case 'col.restore':
 | |
|                     $changeset->columnRestore($input->id);
 | |
|                     $resp = $changeset->fetchAndTransformColumn($input->id);
 | |
|                     break;
 | |
| 
 | |
|                 case 'col.add':
 | |
|                     $resp = $changeset->addBlankCol();
 | |
|                     break;
 | |
| 
 | |
|                 case 'col.sort':
 | |
|                     $changeset->setColOrder($input->order);
 | |
|                     $resp = !empty($changeset->columnOrder); // return flag if order is changed
 | |
|                     break;
 | |
| 
 | |
|                 case 'note.set':
 | |
|                     $changeset->note = $input->text;
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.col-order': // called via POST or GET
 | |
|                     $changeset->resetColumnOrder();
 | |
|                     $resp = $changeset->fetchAndTransformColumns(); // return all columns
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.col-remove': // called via GET
 | |
|                     $changeset->resetRemovedColumns();
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.col-add': // called via GET
 | |
|                     $changeset->resetAddedColumns();
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.col-update': // called via GET
 | |
|                     $changeset->resetUpdatedColumns();
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.row-remove': // called via GET
 | |
|                     $changeset->resetRemovedRows();
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.row-add': // called via GET
 | |
|                     $changeset->resetAddedRows();
 | |
|                     break;
 | |
| 
 | |
|                 case 'reset.row-update': // called via GET
 | |
|                     $changeset->resetUpdatedRows();
 | |
|                     break;
 | |
| 
 | |
|                 default:
 | |
|                     $resp = "Bad Action";
 | |
|                     $code = 400;
 | |
|                     break;
 | |
|             }
 | |
|         } catch (SimpleValidationException $e) {
 | |
|             return $this->jsonResponse(['errors' => $e->getMessageBag()->getMessages()], 400);
 | |
|         }
 | |
| 
 | |
|         $this->storeChangeset($changeset);
 | |
| 
 | |
|         if ($request->method() == 'GET') {
 | |
|             return back();
 | |
|         }
 | |
| 
 | |
|         // Redirect requested via form
 | |
|         if ($code == 200 && $input->has('redirect')) {
 | |
|             return redirect($input->redirect);
 | |
|         }
 | |
| 
 | |
|         return $this->jsonResponse($resp, $code);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Submit the form
 | |
|      *
 | |
|      * @param Request $request
 | |
|      * @param User $user
 | |
|      * @param string $table
 | |
|      * @return \Symfony\Component\HttpFoundation\Response
 | |
|      */
 | |
|     public function draftSubmit(Request $request, User $user, string $table)
 | |
|     {
 | |
|         /** @var Table $tableModel */
 | |
|         $tableModel = $user->tables()->where('name', $table)->first();
 | |
|         if ($tableModel === null) abort(404, "No such table.");
 | |
| 
 | |
|         $input = $this->validate($request, [
 | |
|             'note' => 'required|string'
 | |
|         ]);
 | |
| 
 | |
|         $changeset = $this->getChangeset($tableModel);
 | |
|         $changeset->note = trim($input->note);
 | |
|         if (empty($changeset->note)) throw new SimpleValidationException('note', 'Note is required.');
 | |
| 
 | |
|         if (!$changeset->getRowChangeCounts()->any && !$changeset->getColumnChangeCounts()->any) {
 | |
|             flash()->error("There are no changes to submit.");
 | |
|             return back();
 | |
|         }
 | |
| 
 | |
|         $proposal = Proposal::fromChangeset($changeset);
 | |
|         $proposal->saveOrFail();
 | |
| 
 | |
|         if (\user()->ownsTable($tableModel)) {
 | |
|             $proposal->createRevision();
 | |
|         } else {
 | |
|             // TODO send a notification to the table owner
 | |
|         }
 | |
| 
 | |
|         session()->forget($tableModel->draftSessionKey);
 | |
| 
 | |
|         return redirect($tableModel->viewRoute);
 | |
|     }
 | |
| }
 | |
| 
 |