Passed
Push — master ( 054b32...1c77af )
by Ron
07:39 queued 12s
created

TechTipsController   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 423
Duplicated Lines 0 %

Test Coverage

Coverage 84.76%

Importance

Changes 0
Metric Value
eloc 206
c 0
b 0
f 0
dl 0
loc 423
ccs 178
cts 210
cp 0.8476
rs 8.8798
wmc 44

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A store() 0 40 4
A index() 0 7 1
A edit() 0 19 2
B storeUpdatedTip() 0 55 7
A processImage() 0 15 1
A show() 0 16 3
B search() 0 38 6
A createTip() 0 58 5
A create() 0 11 1
A toggleFav() 0 22 3
A update() 0 38 4
A saveFile() 0 33 3
A details() 0 7 2
A destroy() 0 11 1

How to fix   Complexity   

Complex Class

Complex classes like TechTipsController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TechTipsController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Http\Controllers\TechTips;
4
5
use App\User;
6
use App\Files;
7
use App\TechTips;
8
use App\TechTipFavs;
9
use App\TechTipFiles;
10
use App\TechTipTypes;
11
use App\TechTipSystems;
12
use Illuminate\Http\File;
13
use App\SystemCategories;
14
use Illuminate\Http\Request;
15
use App\Notifications\NewTechTip;
16
use Illuminate\Http\UploadedFile;
17
use Illuminate\Support\Facades\Log;
18
use App\Http\Controllers\Controller;
19
use Illuminate\Support\Facades\Auth;
20
use Illuminate\Support\Facades\Route;
21
use Illuminate\Support\Facades\Storage;
22
use App\Http\Resources\TechTipsCollection;
23
use Illuminate\Support\Facades\Notification;
24
use App\Http\Resources\TechTipTypesCollection;
25
use App\Http\Resources\SystemCategoriesCollection;
26
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;
27
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
28
use App\Http\Resources\SystemCategoriesCollection as CategoriesCollection;
29
30
class TechTipsController extends Controller
31
{
32 80
    public function __construct()
33
    {
34 80
        $this->middleware('auth');
35 80
    }
36
37
    //  Tech Tips landing page
38 2
    public function index()
39
    {
40 2
        $tipTypes = new TechTipTypesCollection(TechTipTypes::all());
41 2
        $sysList  = new CategoriesCollection(SystemCategories::with('SystemTypes')->with('SystemTypes.SystemDataFields.SystemDataFieldTypes')->get());
42 2
        return view('tips.index', [
43 2
            'tipTypes' => $tipTypes,
44 2
            'sysTypes' => $sysList,
45
        ]);
46
    }
47
48
    //  Search for an existing tip - If no paramaters, return all tips
49 8
    public function search(Request $request)
50
    {
51 8
        Log::debug('request Data -> ', $request->toArray());
52
53
        //  See if there are any search paramaters entered
54 8
        if (!$request->search['searchText'] && !isset($request->search['articleType']) && !isset($request->search['systemType'])) {
55
            //  No search paramaters, send all tech tips
56 2
            $tips = new TechTipsCollection(
57 2
                TechTips::orderBy('created_at', 'DESC')
58 2
                    ->with('SystemTypes')
59 2
                    ->paginate($request->pagination['perPage'])
60
            );
61
        } else {
62 6
            $article = isset($request->search['articleType']) ? true : false;
63 6
            $system  = isset($request->search['systemType'])  ? true : false;
64
            //  Search paramaters, filter results
65 6
            $tips = new TechTipsCollection(
66 6
                TechTips::orderBy('created_at', 'DESC')
67
                    //  Search by id or a phrase in the title or description
68
                    ->where(function ($query) use ($request) {
69 6
                        $query->where('subject', 'like', '%' . $request->search['searchText'] . '%')
70 6
                            ->orWhere('tip_id', 'like', '%' . $request->search['searchText'] . '%')
71 6
                            ->orWhere('description', 'like', '%' . $request->search['searchText'] . '%');
72 6
                    })
73
                    ->when($article, function ($query) use ($request) {
74 2
                        $query->whereIn('tip_type_id', $request->search['articleType']);
75 6
                    })
76
                    ->when($system, function ($query) use ($request) {
77
                        $query->whereHas('SystemTypes', function ($query) use ($request) {
78 2
                            $query->whereIn('system_types.sys_id', $request->search['systemType']);
79 2
                        });
80 6
                    })
81 6
                    ->with('SystemTypes')
82 6
                    ->paginate($request->pagination['perPage'])
83
            );
84
        }
85
86 8
        return $tips;
87
    }
88
89
    //  Process an image that is attached to a tech tip
90 6
    public function processImage(Request $request)
91
    {
92 6
        $this->authorize('hasAccess', 'Create Tech Tip');
93
94 4
        $request->validate([
95 4
            'file' => 'mimes:jpeg,bmp,png,jpg,gif'
96
        ]);
97
98
        //  Generate a unique hash as the file name and store it in a publicly accessable folder
99 2
        $path = 'img/tip_img';
100 2
        $location = Storage::disk('public')->putFile($path, new File($request->file));
101
102
        //  Return the full url path to the image
103 2
        Log::debug('Route '.Route::currentRouteName().' visited by User ID-'.Auth::user()->user_id);
104 2
        return response()->json(['location' => Storage::url($location)]);
105
    }
106
107
    //  Create a new Tech Tip form
108 4
    public function create()
109
    {
110 4
        $this->authorize('hasAccess', 'Create Tech Tip');
111
112 2
        $typesArr   = new TechTipTypesCollection(TechTipTypes::all());
113 2
        $systemsArr = new SystemCategoriesCollection(SystemCategories::with('SystemTypes')->get());
114
115 2
        Log::debug('Route '.Route::currentRouteName().' visited by User ID-'.Auth::user()->user_id);
116 2
        return view('tips.create', [
117 2
            'tipTypes' => $typesArr,
118 2
            'sysTypes' => $systemsArr,
119
        ]);
120
    }
121
122
    //  Submit the form to create a new tech tip
123 14
    public function store(Request $request)
124
    {
125 14
        $this->authorize('hasAccess', 'Create Tech Tip');
126
127 12
        $request->validate([
128 12
            'subject'   => 'required',
129
            'equipment' => 'required',
130
            'tipType'   => 'required',
131
            'tip'       => 'required',
132
        ]);
133
134 4
        $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));
135
136
        //  Verify if there is a file to be processed or not
137 4
        if($receiver->isUploaded() === false || $request->_completed)
138
        {
139 4
            Log::debug('about to create a tip');
140 4
            $tipID = $this->createTip($request);
141 4
            Log::debug('Route '.Route::currentRouteName().' visited by User ID-'.Auth::user()->user_id);
142 4
            return response()->json(['tip_id' => $tipID]);
143
        }
144
145
        //  Recieve and process the file
146 2
        $save = $receiver->receive();
147
148
        //  See if the uploade has finished
149 2
        if ($save->isFinished()) {
150 2
            $this->saveFile($save->getFile());
151
152 2
            return 'uploaded successfully';
153
        }
154
155
        //  Get the current progress
156
        $handler = $save->handler();
157
158
        Log::debug('Route ' . Route::currentRouteName() . ' visited by User ID-' . Auth::user()->user_id);
159
        Log::debug('File being uploaded.  Percentage done - ' . $handler->getPercentageDone());
160
        return response()->json([
161
            'done'   => $handler->getPercentageDone(),
162
            'status' => true
163
        ]);
164
    }
165
166
    //  Save a file attached to the link
167 4
    private function saveFile(UploadedFile $file, $id = '_tmp')
168
    {
169 4
        $filePath = config('filesystems.paths.tips').DIRECTORY_SEPARATOR.$id;
170
171
        //  Clean the file and store it
172 4
        $fileName = Files::cleanFilename($filePath, $file->getClientOriginalName());
173 4
        $file->storeAs($filePath, $fileName);
174
175
        //  Place file in Files table of DB
176 4
        $newFile = Files::create([
177 4
            'file_name' => $fileName,
178 4
            'file_link' => $filePath.DIRECTORY_SEPARATOR
179
        ]);
180 4
        $fileID = $newFile->file_id;
181
182
        //  Save the file ID in the session array
183 4
        if($id === '_tmp')
184
        {
185 2
            $fileArr = session('newTipFile') != null ? session('newTipFile') : [];
186 2
            $fileArr[] = $fileID;
187 2
            session(['newTipFile' => $fileArr]);
188
        }
189
        else
190
        {
191 2
            TechTipFiles::create([
192 2
                'tip_id' => $id,
193 2
                'file_id' => $fileID,
194
            ]);
195
        }
196
197
        //  Log stored file
198 4
        Log::info('File Stored', ['file_id' => $fileID, 'file_path' => $filePath . DIRECTORY_SEPARATOR . $fileName]);
199 4
        return $fileID;
200
    }
201
202
    //  Create the tech tip
203 4
    private function createTip($tipData)
204
    {
205
        //  Remove any forward slash (/) from the Subject Field
206 4
        $tipData->merge(['subject' => str_replace('/', '-', $tipData->subject)]);
207
208
        //  Enter the tip details and return the tip ID
209 4
        $tip = TechTips::create([
210 4
            'tip_type_id' => $tipData->tipType,
211 4
            'subject'     => $tipData->subject,
212 4
            'description' => $tipData->tip,
213 4
            'user_id'     => Auth::user()->user_id
214
        ]);
215 4
        $tipID = $tip->tip_id;
216
217 4
        foreach($tipData->equipment as $sys)
218
        {
219 4
            TechTipSystems::create([
220 4
                'tip_id' => $tipID,
221 4
                'sys_id' => $sys['sys_id']
222
            ]);
223
        }
224
225
        //  If there were any files uploaded, move them to the proper folder
226 4
        if(session('newTipFile') != null)
227
        {
228 2
            $files = session('newTipFile');
229 2
            $path = config('filesystems.paths.tips').DIRECTORY_SEPARATOR.$tipID;
230 2
            foreach($files as $file)
231
            {
232 2
                $data = Files::find($file);
233
                //  Move the file to the proper folder
234 2
                Storage::move($data->file_link.$data->file_name, $path.DIRECTORY_SEPARATOR.$data->file_name);
235
                // Update the database
236 2
                $data->update([
237 2
                    'file_link' => $path.DIRECTORY_SEPARATOR
238
                ]);
239
240 2
                TechTipFiles::create([
241 2
                    'tip_id' => $tipID,
242 2
                    'file_id' => $data->file_id
243
                ]);
244
            }
245
        }
246
247
        //  Send out the notifications
248 4
        if(!$tipData->supressEmail)
249
        {
250 4
            $details = TechTips::find($tipID);
251
            $users = User::whereHas('UserSettings', function($query)
252
            {
253 4
                $query->where('em_tech_tip', 1);
254 4
            })->get();
255
256 4
            Notification::send($users, new NewTechTip($details));
257
        }
258
259 4
        Log::info('New Tech Tip created.  Tip Data - ', $tip->toArray());
260 4
        return $tipID;
261
    }
262
263
    //  Details controller - will move to the show controller with just the tech tip id
264 2
    public function details($id, $subject)
265
    {
266 2
        if (session()->has('newTipFile')) {
267
            session()->forget('newTipFile');
268
        }
269
270 2
        return $this->show($id);
271
    }
272
273
    //  Show the details about the tech tip
274 2
    public function show($id)
275
    {
276 2
        $tipData = TechTips::where('tip_id', $id)->with('User')->with('SystemTypes')->first();
277
278 2
        if(!$tipData)
279
        {
280
            return view('tips.tipNotFound');
281
        }
282
283 2
        $isFav = TechTipFavs::where('user_id', Auth::user()->user_id)->where('tip_id', $id)->first();
284 2
        $files = TechTipFiles::where('tip_id', $id)->with('Files')->get();
285
286 2
        return view('tips.details', [
287 2
            'details' => $tipData,
288 2
            'isFav'   => empty($isFav) ? 'false' : 'true',
289 2
            'files'   => $files,
290
        ]);
291
    }
292
293
    //  Add or remove this tip as a favorite of the user
294
    public function toggleFav($action, $id)
295
    {
296
        switch ($action) {
297
            case 'add':
298
                TechTipFavs::create([
299
                    'user_id' => Auth::user()->user_id,
300
                    'tip_id' => $id
301
                ]);
302
                break;
303
            case 'remove':
304
                $tipFav = TechTipFavs::where('user_id', Auth::user()->user_id)->where('tip_id', $id)->first();
305
                $tipFav->delete();
306
                break;
307
        }
308
309
        Log::debug('Route ' . Route::currentRouteName() . ' visited by User ID-' . Auth::user()->user_id);
310
        Log::debug('Tech Tip Bookmark Updated.', [
311
            'user_id' => Auth::user()->user_id,
312
            'tip_id' => $id,
313
            'action'  => $action
314
        ]);
315
        return response()->json(['success' => true]);
316
    }
317
318
    //  Edit an existing tech tip
319 6
    public function edit($id)
320
    {
321 6
        $this->authorize('hasAccess', 'Edit Tech Tip');
322 4
        $tipData = TechTips::where('tip_id', $id)->with('User')->with('SystemTypes')->with('TechTipTypes')->first();
323
324 4
        if (!$tipData) {
325 2
            return view('tips.tipNotFound');
326
        }
327
328 2
        $typesArr   = new TechTipTypesCollection(TechTipTypes::all());
329 2
        $systemsArr = new SystemCategoriesCollection(SystemCategories::with('SystemTypes')->get());
330 2
        $files = TechTipFiles::where('tip_id', $id)->with('Files')->get();
331
332 2
        Log::debug('Route ' . Route::currentRouteName() . ' visited by User ID-' . Auth::user()->user_id);
333 2
        return view('tips.editTip', [
334 2
            'tipTypes' => $typesArr,
335 2
            'sysTypes' => $systemsArr,
336 2
            'details' => $tipData,
337 2
            'files'   => $files,
338
        ]);
339
    }
340
341
    //  Store the edited Tech Tip
342 16
    public function update(Request $request, $id)
343
    {
344 16
        $this->authorize('hasAccess', 'Edit Tech Tip');
345
346 14
        $request->validate([
347 14
            'subject'   => 'required',
348
            'equipment' => 'required',
349
            'tipType'   => 'required',
350
            'tip'       => 'required',
351
        ]);
352
353 6
        $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));
354
355
        //  Verify if there is a file to be processed or not
356 6
        if ($receiver->isUploaded() === false || $request->_completed) {
357 6
            $this->storeUpdatedTip($request, $id);
358 6
            Log::debug('Route ' . Route::currentRouteName() . ' visited by User ID-' . Auth::user()->user_id);
359 6
            return response()->json(['tip_id' => $id]);
360
        }
361
362
        //  Recieve and process the file
363 2
        $save = $receiver->receive();
364
365
        //  See if the uploade has finished
366 2
        if ($save->isFinished()) {
367 2
            $this->saveFile($save->getFile(), $id);
368
369 2
            return 'uploaded successfully';
370
        }
371
372
        //  Get the current progress
373
        $handler = $save->handler();
374
375
        Log::debug('Route ' . Route::currentRouteName() . ' visited by User ID-' . Auth::user()->user_id);
376
        Log::debug('File being uploaded.  Percentage done - ' . $handler->getPercentageDone());
377
        return response()->json([
378
            'done'   => $handler->getPercentageDone(),
379
            'status' => true
380
        ]);
381
    }
382
383
    //  Store the updated tip
384 6
    public function storeUpdatedTip($tipData, $id)
385
    {
386 6
        $this->authorize('hasAccess', 'Edit Tech Tip');
387
388
        //  Remove any forward slash (/) from the Subject Field
389 6
        $tipData->merge(['subject' => str_replace('/', '-', $tipData->subject)]);
390
391
        //  Enter the tip details and return the tip ID
392 6
        TechTips::find($id)->update([
393 6
            'tip_type_id' => $tipData->tipType,
394 6
            'subject'     => $tipData->subject,
395 6
            'description' => $tipData->tip,
396
            // 'user_id'     => Auth::user()->user_id TODO - updated user who modified tip
397
        ]);
398
399
        //  Add any additional equipment types to the tip
400 6
        $tipEquip = TechTipSystems::where('tip_id', $id)->get();
401 6
        foreach($tipData->equipment as $equip)
402
        {
403 6
            $found = false;
404 6
            foreach($tipEquip as $key => $value)
405
            {
406 6
                if($equip['sys_id'] == $value->sys_id)
407
                {
408
                    $tipEquip->forget($key);
409
                    $found = true;
410
                    break;
411
                }
412
            }
413 6
            if(!$found)
414
            {
415 6
                TechTipSystems::create([
416 6
                    'tip_id' => $id,
417 6
                    'sys_id' => $equip['sys_id'],
418
                ]);
419
            }
420
        }
421
422
        //  Remove the remainaing equipment types that have been removed
423 6
        foreach($tipEquip as $remaining)
424
        {
425 6
            TechTipSystems::find($remaining->tip_tag_id)->delete();
426
        }
427
428
        //  Remove any files that no longer apply
429 6
        foreach($tipData->deletedFileList as $file)
430
        {
431 2
            $file = TechTipFiles::find($file);
432 2
            $fileID = $file->file_id;
433 2
            $file->delete();
434
            //  Try to delete the file itself
435 2
            Files::deleteFile($fileID);
436
        }
437
438 6
        return true;
439
    }
440
441
    //  Soft delet the Tech Tip
442 4
    public function destroy($id)
443
    {
444 4
        $this->authorize('hasAccess', 'Delete Tech Tip');
445
446
        //  Remove the Tip from any users favorites
447 2
        TechTipFavs::where('tip_id', $id)->delete();
448
449
        //  Disable the tip
450 2
        TechTips::find($id)->delete();
451 2
        Log::warning('User - '.Auth::user()->user_id.' deleted Tech Tip ID - '.$id);
452 2
        return response()->json(['success' => true]);
453
    }
454
}
455