ImportCrudController   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 332
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 27
eloc 107
dl 0
loc 332
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A setWizardData() 0 5 1
A setup() 0 41 1
A update() 0 7 1
A createBatch() 0 12 2
F importProject() 0 59 13
A store() 0 7 1
A __construct() 0 6 1
A processImportProject() 0 33 3
A getWizardStep() 0 35 4
1
<?php
2
3
namespace App\Http\Controllers\Frontend;
4
5
// VALIDATION: change the requests to match your own file names if you need form validation
6
use App\Http\Requests\Frontend\ImportRequest;
7
use App\Http\Requests\Frontend\ImportRequest as StoreRequest;
8
use App\Http\Requests\Frontend\ImportRequest as UpdateRequest;
9
use App\Http\Traits\UsesEnums;
10
use App\Http\Traits\UsesPolicies;
11
use App\Models\Batch;
12
use App\Models\Import;
13
use App\Models\Project;
14
use App\Wizard\Import\ProjectSteps\ApproveImportStep;
15
use App\Wizard\Import\ProjectSteps\DisplayResultsStep;
16
use App\Wizard\Import\ProjectSteps\SelectWorksheetsStep;
17
use App\Wizard\Import\ProjectSteps\SetSpreadsheetStep;
18
use Backpack\CRUD\app\Http\Controllers\CrudController;
19
use Illuminate\Http\RedirectResponse;
20
use Illuminate\Http\Request;
21
use Smajti1\Laravel\Exceptions\StepNotFoundException;
22
use Smajti1\Laravel\Wizard;
23
use const null;
24
use function method_exists;
25
26
class ImportCrudController extends CrudController
27
{
28
    use UsesPolicies, UsesEnums;
29
    /**
30
     * @var array
31
     */
32
    public $steps = [
33
        'spreadsheet' => SetSpreadsheetStep::class,
34
        'worksheets'  => SelectWorksheetsStep::class,
35
        'approve'     => ApproveImportStep::class,
36
        'report'      => DisplayResultsStep::class,
37
    ];
38
    /**
39
     * @var Wizard
40
     */
41
    protected $wizard;
42
43
    /**
44
     * ImportCrudController constructor.
45
     *
46
     * @throws \Smajti1\Laravel\Exceptions\StepNotFoundException
47
     */
48
    public function __construct()
49
    {
50
        parent::__construct();
51
        $this->wizard = new Wizard($this->steps, $sessionKeyName = 'project-import');
52
53
        view()->share(['wizard' => $this->wizard]);
54
    }
55
56
    /**
57
     * @throws \Exception
58
     */
59
    public function setup()
60
    {
61
        /*
62
        |--------------------------------------------------------------------------
63
        | BASIC CRUD INFORMATION
64
        |--------------------------------------------------------------------------
65
        */
66
        $this->crud->setModel(Import::class);
67
        $this->crud->setRoute(config('backpack.base.route_prefix') . '/projects/' . request()->project . '/imports');
68
        $this->crud->setEntityNameStrings('Import', 'Imports');
69
        $this->addCustomDoctrineColumnTypes();
70
        //$this->crud->setFromDb();
71
72
        // ------ CRUD FIELDS
73
74
        // $this->crud->addFields();
75
        // $this->crud->addFields($array_of_arrays, 'update/create/both');
76
        // $this->crud->removeField('name', 'update/create/both');
77
        // $this->crud->removeFields($array_of_names, 'update/create/both');
78
79
        // ------ CRUD COLUMNS
80
        // $this->crud->addColumn(); // add a single column, at the end of the stack
81
        // $this->crud->addColumns(); // add multiple columns, at the end of the stack
82
        // $this->crud->removeColumn('column_name'); // remove a column from the stack
83
        // $this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
84
        // $this->crud->setColumnDetails('column_name', ['attribute' => 'value']); // adjusts the properties of the passed in column (by name)
85
        // $this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
86
87
        // ------ CRUD BUTTONS
88
        // possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
89
        // $this->crud->addButton($stack, $name, $type, $content, $position); // add a button; possible types are: view, model_function
90
        // $this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position); // add a button whose HTML is returned by a method in the CRUD model
91
        // $this->crud->addButtonFromView($stack, $name, $view, $position); // add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
92
        // $this->crud->removeButton($name);
93
        // $this->crud->removeButtonFromStack($name, $stack);
94
        // $this->crud->removeAllButtons();
95
        // $this->crud->removeAllButtonsFromStack('line');
96
97
        // ------ CRUD ACCESS
98
        $this->crud->allowAccess(['list', 'show']);
99
        $this->crud->denyAccess(['create', 'update', 'delete', 'importProject']);
100
101
        // ------ CRUD REORDER
102
        // $this->crud->enableReorder('label_name', MAX_TREE_LEVEL);
103
        // NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('reorder');
104
105
        // ------ CRUD DETAILS ROW
106
        // $this->crud->enableDetailsRow();
107
        // NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
108
        // NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
109
110
        // ------ REVISIONS
111
        // You also need to use \Venturecraft\Revisionable\RevisionableTrait;
112
        // Please check out: https://laravel-backpack.readme.io/docs/crud#revisions
113
        // $this->crud->allowAccess('revisions');
114
115
        // ------ AJAX TABLE VIEW
116
        // Please note the drawbacks of this though:
117
        // - 1-n and n-n columns are not searchable
118
        // - date and datetime columns won't be sortable anymore
119
        // $this->crud->enableAjaxTable();
120
121
        // ------ DATATABLE EXPORT BUTTONS
122
        // Show export to PDF, CSV, XLS and Print buttons on the table view.
123
        // Does not work well with AJAX datatables.
124
        // $this->crud->enableExportButtons();
125
126
        // ------ ADVANCED QUERIES
127
        // $this->crud->addClause('active');
128
        // $this->crud->addClause('type', 'car');
129
        // $this->crud->addClause('where', 'name', '==', 'car');
130
        // $this->crud->addClause('whereName', 'car');
131
        // $this->crud->addClause('whereHas', 'posts', function($query) {
132
        //     $query->activePosts();
133
        // });
134
        // $this->crud->addClause('withoutGlobalScopes');
135
        // $this->crud->addClause('withoutGlobalScope', VisibleScope::class);
136
        // $this->crud->with(); // eager load relationships
137
        // $this->crud->orderBy();
138
        // $this->crud->groupBy();
139
        // $this->crud->limit();
140
    }
141
142
    /**
143
     * @param UpdateRequest $request
144
     * @param Project       $project
145
     *
146
     * @return RedirectResponse
147
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
148
     * @throws \Illuminate\Auth\Access\AuthorizationException
149
     */
150
    public function createBatch(ImportRequest $request, Project $project)
151
    {
152
        $this->policyAuthorize('import', $project, $project->id);
153
        /* @var Batch $batch */
154
        if ($this->wizard->dataHas('batch_id')) {
155
            $batch = Batch::findOrFail($this->wizard->dataGet('batch_id'));
156
        } else {
157
            $batch = Batch::make(['project_id' => $project->id, 'user_id' => auth()->id()]);
158
            $this->setWizardData('batch_id', $batch->id);
159
        }
160
161
        return $this->processImportProject($request, $project, $batch, $this->wizard->first()->key);
162
    }
163
164
    /**
165
     * @param Request $request
166
     * @param Project $project
167
     * @param Batch   $batch
168
     * @param int|null     $step
169
     *
170
     * @return \Illuminate\Http\Response
171
     * @throws \Illuminate\Auth\Access\AuthorizationException
172
     */
173
    public function importProject(Request $request, Project $project, Batch $batch, $step = null)
174
    {
175
        $this->policyAuthorize('import', $project, $project->id);
176
        //if we get to here we're authorized to import a project, so we authorize create
177
        $this->crud->allowAccess(['create', 'edit']);
178
        try {
179
            if ($step === null) {
180
                if ($batch->id === null) {
181
                    $step = $this->wizard->first();
182
                    $this->wizard->data([]);
183
                } else {
184
                    $step = $this->wizard->firstOrLastProcessed();
185
                }
186
            } else {
187
                $step = $this->wizard->getBySlug($step);
188
            }
189
        } catch (StepNotFoundException $e) {
190
            abort(404);
191
        }
192
        //we've jumped into a middle step of the sequence (we should always have worksheets after step 1)
193
        if ($step->number > 1 && ! $batch->dataHas('googlesheets')) {
194
            $step = $this->wizard->first();
195
        }
196
        if ($this->wizard->data() != $batch->step_data) {
197
            //we've returned from an incomplete import
198
            //and have to load the previous step data into the wizard from the database
199
            $this->wizard->data($batch->step_data);
200
        }
201
202
        $this->setWizardData('batch_id', $batch->id);
203
        $this->setWizardData('project_id', $project->id);
204
205
        if (method_exists($step, 'preProcess')) {
206
            $step->preProcess($request, $this->wizard);
207
        }
208
209
        $this->crud->setCreateView('frontend.import.project.wizard');
210
        $this->crud->setRoute(config('backpack.base.route_prefix') . 'projects/' . $project->id);
211
        $this->crud->addFields($step->fields(), 'create');
212
        $this->data['step']        = $step;
213
        $this->data['project']     = $project;
214
        $this->data['batch']       = $batch;
215
        $this->data['wizard_data'] = $this->wizard->data();
216
        if (isset($this->wizard->data()[$step->key])) {
217
            $data = $this->wizard->data()[$step->key];
218
            if ($step->key === 'spreadsheet') {
219
                foreach ($data as $key => $datum) {
220
                    $this->crud->create_fields[$key]['value'] = $datum;
221
                }
222
            }
223
            if ($step->key === 'worksheets') {
224
                $this->crud->create_fields['worksheets']['value'] = $data;
225
            }
226
            if ($step->key === 'approve') {
227
                $this->crud->create_fields['approve']['value'] = $data;
228
            }
229
        }
230
231
        return parent::create();
232
    }
233
234
    /**
235
     * @param UpdateRequest $request
236
     * @param Project       $project
237
     * @param Batch         $batch
238
     * @param null          $step
239
     *
240
     * @return RedirectResponse
241
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
242
     * @throws \Illuminate\Auth\Access\AuthorizationException
243
     */
244
    public function processImportProject(ImportRequest $request, Project $project, Batch $batch, $step = null): RedirectResponse
245
    {
246
        $this->policyAuthorize('import', $project, $project->id);
247
        //if we get to here we're authorized to import a project, so we authorize create
248
        $this->crud->allowAccess(['create']);
249
        try {
250
            $step = $this->wizard->getBySlug($step);
251
        } catch (StepNotFoundException $e) {
252
            abort(404);
253
        }
254
255
        //here we validate the input from the step
256
257
        if (method_exists($step, 'validate')) {
258
            $step->validate($request);
259
        } else {
260
            $this->validate($request, $step->rules($request));
261
        }
262
263
        //$request->flash();
264
265
        //handle the next/last step
266
        $step->process($request);
267
268
        $batch->step_data       = $this->wizard->data();
269
        $batch->next_step       = $this->wizard->nextSlug();
270
        $batch->run_description = $batch->run_description ?? $this->wizard->dataGet('title');
271
        $batch->save();
272
273
        //and redirect to the next step if valid
274
        //$request->session()->save();
275
        return redirect()->route('frontend.project.import',
276
            ['project' => $project->id, 'batch' => $batch, 'step' => $this->wizard->nextSlug()]);
277
    }
278
279
    /**
280
     * @param UpdateRequest $request
281
     *
282
     * @return RedirectResponse
283
     */
284
    public function store(StoreRequest $request)
285
    {
286
        // your additional operations before save here
287
        $redirect_location = parent::storeCrud();
288
        // your additional operations after save here
289
        // use $this->data['entry'] or $this->crud->entry
290
        return $redirect_location;
291
    }
292
293
    /**
294
     * @param UpdateRequest $request
295
     *
296
     * @return RedirectResponse
297
     */
298
    public function update(UpdateRequest $request)
299
    {
300
        // your additional operations before save here
301
        $redirect_location = parent::updateCrud();
302
        // your additional operations after save here
303
        // use $this->data['entry'] or $this->crud->entry
304
        return $redirect_location;
305
    }
306
307
    /**
308
     * @param $step
309
     *
310
     * @return array
311
     */
312
    private static function getWizardStep($step): array
0 ignored issues
show
Unused Code introduced by
The method getWizardStep() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
313
    {
314
        $steps = [
315
            [
316
                'name'         => 'spreadsheet',
317
                'step'         => 1,
318
                'title'        => 'Start with a Spreadsheet URL...',
319
                'instructions' => 'Some instructions',
320
            ],
321
            [
322
                'name'         => 'worksheets',
323
                'step'         => 2,
324
                'title'        => 'Choose the Worksheets...',
325
                'instructions' => 'Some instructions',
326
            ],
327
            [
328
                'name'         => 'approve',
329
                'step'         => 3,
330
                'title'        => 'Approve the changes..',
331
                'instructions' => 'Some instructions',
332
            ],
333
            [
334
                'name'         => 'import',
335
                'step'         => 4,
336
                'title'        => 'Start with a Spreadsheet URL',
337
                'instructions' => 'Some instructions',
338
            ],
339
        ];
340
        $key   = $step !== null ? array_search($step, array_column($steps, 'name')) : 0;
341
        if ($key === false) {
342
            abort(404, 'Invalid Step');
343
        }
344
        $steps[$key]['next'] = ($key < count($steps)) ? $steps[$key + 1]['name'] : false;
345
346
        return $steps[$key];
347
    }
348
349
    /**
350
     * @param string $key
351
     * @param mixed  $value
352
     */
353
    private function setWizardData($key, $value): void
354
    {
355
        $data         = $this->wizard->data();
356
        $data[$key]   = $value;
357
        $this->wizard->data($data);
358
    }
359
}
360