AdminController   F
last analyzed

Complexity

Total Complexity 121

Size/Duplication

Total Lines 732
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
eloc 365
dl 0
loc 732
rs 2
c 9
b 0
f 0
wmc 121

38 Methods

Rating   Name   Duplication   Size   Complexity  
A showFileEditor() 0 3 1
A showSitePage() 0 4 1
A showBackups() 0 3 1
A redirectInfo() 0 33 3
A pagesPrivacy() 0 11 2
A authAs() 0 20 3
A showLinksUser() 0 8 1
A delAvatar() 0 11 2
A isValidLink() 0 9 3
A verifyCheckUser() 0 15 3
A pagesTerms() 0 11 2
A random_str() 0 13 3
A removeFolder() 0 8 2
A deleteTableUser() 0 12 1
A deleteLinkUser() 0 7 1
A delFavicon() 0 12 2
A editSite() 0 34 5
A blockUser() 0 14 3
A pagesContact() 0 11 2
A editSitePage() 0 10 1
B editUser() 0 48 9
A SendTestMail() 0 14 2
A editAC() 0 9 2
A createNewUser() 0 43 5
A phpinfo() 0 3 1
A users() 0 3 1
A showUser() 0 7 1
A authAsID() 0 19 2
A showSite() 0 4 1
A verifyUser() 0 12 2
A index() 0 39 1
A editENV() 0 7 1
A showThemes() 0 3 1
A showConfig() 0 3 1
A deleteUser() 0 14 1
F editConfig() 0 53 36
A deleteTheme() 0 29 3
C updateThemes() 0 92 17

How to fix   Complexity   

Complex Class

Complex classes like AdminController 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 AdminController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Http\Controllers;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Facades\Hash;
7
use Illuminate\Auth\Events\Registered;
8
use Illuminate\Support\Facades\Schema;
9
use Illuminate\Support\Facades\File;
10
use Illuminate\Support\Facades\Mail;
11
12
use GeoSot\EnvEditor\Controllers\EnvController;
13
use GeoSot\EnvEditor\Exceptions\EnvException;
14
use GeoSot\EnvEditor\Helpers\EnvFileContentManager;
15
use GeoSot\EnvEditor\Helpers\EnvFilesManager;
16
use GeoSot\EnvEditor\Helpers\EnvKeysManager;
17
use GeoSot\EnvEditor\Facades\EnvEditor;
18
use GeoSot\EnvEditor\ServiceProvider;
19
20
use Auth;
21
use Exception;
22
use ZipArchive;
23
use Carbon\Carbon;
24
25
use App\Models\User;
26
use App\Models\Admin;
27
use App\Models\Button;
28
use App\Models\Link;
29
use App\Models\Page;
30
use App\Models\UserData;
31
32
class AdminController extends Controller
33
{
34
    //Statistics of the number of clicks and links
35
    public function index()
36
    {
37
        $userId = Auth::user()->id;
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
38
        $littlelink_name = Auth::user()->littlelink_name;
0 ignored issues
show
Bug introduced by
Accessing littlelink_name on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
39
        $links = Link::where('user_id', $userId)->select('link')->count();
0 ignored issues
show
Unused Code introduced by
The assignment to $links is dead and can be removed.
Loading history...
40
        $clicks = Link::where('user_id', $userId)->sum('click_number');
0 ignored issues
show
Unused Code introduced by
The assignment to $clicks is dead and can be removed.
Loading history...
41
42
        $userNumber = User::count();
43
        $siteLinks = Link::count();
44
        $siteClicks = Link::sum('click_number');
45
46
        $users = User::select('id', 'name', 'email', 'created_at', 'updated_at')->get();
47
        $lastMonthCount = $users->where('created_at', '>=', Carbon::now()->subDays(30))->count();
48
        $lastWeekCount = $users->where('created_at', '>=', Carbon::now()->subDays(7))->count();
49
        $last24HrsCount = $users->where('created_at', '>=', Carbon::now()->subHours(24))->count();
50
        $updatedLast30DaysCount = $users->where('updated_at', '>=', Carbon::now()->subDays(30))->count();
51
        $updatedLast7DaysCount = $users->where('updated_at', '>=', Carbon::now()->subDays(7))->count();
52
        $updatedLast24HrsCount = $users->where('updated_at', '>=', Carbon::now()->subHours(24))->count();
53
54
        $links = Link::where('user_id', $userId)->select('link')->count();
55
        $clicks = Link::where('user_id', $userId)->sum('click_number');
56
        $topLinks = Link::where('user_id', $userId)->orderby('click_number', 'desc')
57
            ->whereNotNull('link')->where('link', '<>', '')
58
            ->take(5)->get();
59
60
        $pageStats = [
61
            'visitors' => [
62
                'all' => visits('App\Models\User', $littlelink_name)->count(),
63
                'day' => visits('App\Models\User', $littlelink_name)->period('day')->count(),
64
                'week' => visits('App\Models\User', $littlelink_name)->period('week')->count(),
65
                'month' => visits('App\Models\User', $littlelink_name)->period('month')->count(),
66
                'year' => visits('App\Models\User', $littlelink_name)->period('year')->count(),
67
            ],
68
            'os' => visits('App\Models\User', $littlelink_name)->operatingSystems(),
69
            'referers' => visits('App\Models\User', $littlelink_name)->refs(),
70
            'countries' => visits('App\Models\User', $littlelink_name)->countries(),
71
        ];
72
73
        return view('panel/index', ['lastMonthCount' => $lastMonthCount,'lastWeekCount' => $lastWeekCount,'last24HrsCount' => $last24HrsCount,'updatedLast30DaysCount' => $updatedLast30DaysCount,'updatedLast7DaysCount' => $updatedLast7DaysCount,'updatedLast24HrsCount' => $updatedLast24HrsCount,'toplinks' => $topLinks, 'links' => $links, 'clicks' => $clicks, 'pageStats' => $pageStats, 'littlelink_name' => $littlelink_name, 'links' => $links, 'clicks' => $clicks, 'siteLinks' => $siteLinks, 'siteClicks' => $siteClicks, 'userNumber' => $userNumber]);
74
    }
75
76
// Users page
77
public function users()
78
{
79
    return view('panel/users');
80
}
81
82
// Send test mail
83
public function SendTestMail(Request $request)
84
{
85
    try {
86
        $userId = auth()->id();
87
        $user = User::findOrFail($userId);
88
        
89
        Mail::send('auth.test', ['user' => $user], function ($message) use ($user) {
90
            $message->to($user->email)
91
                    ->subject('Test Email');
92
        });
93
        
94
        return redirect()->route('showConfig')->with('success', 'Test email sent successfully!');
95
    } catch (\Exception $e) {
96
        return redirect()->route('showConfig')->with('fail', 'Failed to send test email.');
97
    }
98
}
99
100
    //Block user
101
    public function blockUser(request $request)
102
    {
103
        $id = $request->id;
104
        $status = $request->block;
105
106
        if ($status == 'yes') {
107
            $block = 'no';
108
        } elseif ($status == 'no') {
109
            $block = 'yes';
110
        }
111
112
        User::where('id', $id)->update(['block' => $block]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $block does not seem to be defined for all execution paths leading up to this point.
Loading history...
113
114
        return redirect('admin/users/all');
115
    }
116
117
    //Verify user
118
    public function verifyCheckUser(request $request)
119
    {
120
        $id = $request->id;
121
        $status = $request->verify;
122
123
        if ($status == 'vip') {
124
            $verify = 'vip';
125
            UserData::saveData($id, 'checkmark', true);
126
        } elseif ($status == 'user') {
127
            $verify = 'user';
128
        }
129
130
        User::where('id', $id)->update(['role' => $verify]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $verify does not seem to be defined for all execution paths leading up to this point.
Loading history...
131
132
        return redirect(url('u')."/".$id);
133
    }
134
135
    //Verify or un-verify users emails
136
    public function verifyUser(request $request)
137
    {
138
        $id = $request->id;
139
        $status = $request->verify;
140
141
        if ($status == "true") {
142
            $verify = '0000-00-00 00:00:00';
143
        } else {
144
            $verify = NULL;
145
        }
146
147
        User::where('id', $id)->update(['email_verified_at' => $verify]);
148
    }
149
150
    //Create new user from the Admin Panel
151
    public function createNewUser()
152
    {
153
154
        function random_str(
155
            int $length = 64,
156
            string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
157
        ): string {
158
            if ($length < 1) {
159
                throw new \RangeException("Length must be a positive integer");
160
            }
161
            $pieces = [];
162
            $max = mb_strlen($keyspace, '8bit') - 1;
163
            for ($i = 0; $i < $length; ++$i) {
164
                $pieces[] = $keyspace[random_int(0, $max)];
165
            }
166
            return implode('', $pieces);
167
        }
168
169
        $names = User::pluck('name')->toArray();
170
171
        $adminCreatedNames = array_filter($names, function($name) {
0 ignored issues
show
Bug introduced by
It seems like $names can also be of type Illuminate\Database\Eloq...elations\HasManyThrough and Illuminate\Database\Eloq...Relations\HasOneThrough; however, parameter $array of array_filter() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

171
        $adminCreatedNames = array_filter(/** @scrutinizer ignore-type */ $names, function($name) {
Loading history...
172
            return strpos($name, 'Admin-Created-') === 0;
173
        });
174
175
        $numbers = array_map(function($name) {
176
            return (int) str_replace('Admin-Created-', '', $name);
177
        }, $adminCreatedNames);
178
179
        $maxNumber = !empty($numbers) ? max($numbers) : 0;
180
        $newNumber = $maxNumber + 1;
181
182
        $domain = parse_url(url(''), PHP_URL_HOST);
183
        $domain = ($domain == 'localhost') ? 'example.com' : $domain;
184
185
        $user = User::create([
186
            'name' => 'Admin-Created-' . $newNumber,
187
            'email' => strtolower(random_str(8)) . '@' . $domain,
188
            'password' => Hash::make(random_str(32)),
189
            'role' => 'user',
190
            'block' => 'no',
191
        ]);
192
193
        return redirect('admin/edit-user/' . $user->id);
194
    }
195
196
    //Delete existing user
197
    public function deleteUser(request $request)
198
    {
199
        $id = $request->id;
200
201
        Link::where('user_id', $id)->delete();
202
    
203
        Schema::disableForeignKeyConstraints();
204
        
205
        $user = User::find($id);
206
        $user->forceDelete();
207
    
208
        Schema::enableForeignKeyConstraints();
209
    
210
        return redirect('admin/users/all');
211
    }
212
213
    //Delete existing user with POST request
214
    public function deleteTableUser(request $request)
215
    {
216
        $id = $request->id;
217
218
        Link::where('user_id', $id)->delete();
219
    
220
        Schema::disableForeignKeyConstraints();
221
        
222
        $user = User::find($id);
223
        $user->forceDelete();
224
    
225
        Schema::enableForeignKeyConstraints();
226
    }
227
228
    //Show user to edit
229
    public function showUser(request $request)
230
    {
231
        $id = $request->id;
232
233
        $data['user'] = User::where('id', $id)->get();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
234
235
        return view('panel/edit-user', $data);
236
    }
237
238
    //Show link, click number, up link in links page
239
    public function showLinksUser(request $request)
240
    {
241
        $id = $request->id;
242
243
        $data['user'] = User::where('id', $id)->get();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
244
245
        $data['links'] = Link::select('id', 'link', 'title', 'order', 'click_number', 'up_link', 'links.button_id')->where('user_id', $id)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->paginate(10);
246
        return view('panel/links', $data);
247
    }
248
249
    //Delete link
250
    public function deleteLinkUser(request $request)
251
    {
252
        $linkId = $request->id;
253
254
        Link::where('id', $linkId)->delete();
255
256
        return back();
257
    }
258
259
    //Save user edit
260
    public function editUser(request $request)
261
    {
262
        $request->validate([
263
            'name' => '',
264
            'email' => '',
265
            'password' => '',
266
            'littlelink_name' => '',
267
        ]);
268
269
        $id = $request->id;
270
        $name = $request->name;
271
        $email = $request->email;
272
        $password = Hash::make($request->password);
273
        $profilePhoto = $request->file('image');
274
        $littlelink_name = $request->littlelink_name;
275
        $littlelink_description = $request->littlelink_description;
276
        $role = $request->role;
277
        $customBackground = $request->file('background');
278
        $theme = $request->theme;
279
280
        if(User::where('id', $id)->get('role')->first()->role =! $role) {
281
            if ($role == 'vip') {
282
                UserData::saveData($id, 'checkmark', true);
283
            }
284
        }
285
286
        if ($request->password == '') {
287
            User::where('id', $id)->update(['name' => $name, 'email' => $email, 'littlelink_name' => $littlelink_name, 'littlelink_description' => $littlelink_description, 'role' => $role, 'theme' => $theme]);
288
        } else {
289
            User::where('id', $id)->update(['name' => $name, 'email' => $email, 'password' => $password, 'littlelink_name' => $littlelink_name, 'littlelink_description' => $littlelink_description, 'role' => $role, 'theme' => $theme]);
290
        }
291
        if (!empty($profilePhoto)) {
292
            $profilePhoto->move(base_path('assets/img'), $id . '_' . time() . ".png");
293
        } 
294
        if (!empty($customBackground)) {
295
            $directory = base_path('assets/img/background-img/');
296
            $files = scandir($directory);
297
            $pathinfo = "error.error";
298
            foreach($files as $file) {
299
            if (strpos($file, $id.'.') !== false) {
300
            $pathinfo = $id. "." . pathinfo($file, PATHINFO_EXTENSION);
0 ignored issues
show
Bug introduced by
Are you sure pathinfo($file, App\Http...ers\PATHINFO_EXTENSION) of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

300
            $pathinfo = $id. "." . /** @scrutinizer ignore-type */ pathinfo($file, PATHINFO_EXTENSION);
Loading history...
301
            }}
302
            if(file_exists(base_path('assets/img/background-img/').$pathinfo)){File::delete(base_path('assets/img/background-img/').$pathinfo);}
303
    
304
            $customBackground->move(base_path('assets/img/background-img/'), $id . '_' . time() . "." . $request->file('background')->extension());
305
        } 
306
307
        return redirect('admin/users/all');
308
    }
309
310
    //Show site pages to edit
311
    public function showSitePage()
312
    {
313
        $data['pages'] = Page::select('terms', 'privacy', 'contact', 'register')->get();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
314
        return view('panel/pages', $data);
315
    }
316
317
    //Save site pages
318
    public function editSitePage(request $request)
319
    {
320
        $terms = $request->terms;
321
        $privacy = $request->privacy;
322
        $contact = $request->contact;
323
        $register = $request->register;
324
325
        Page::first()->update(['terms' => $terms, 'privacy' => $privacy, 'contact' => $contact, 'register' => $register]);
326
327
        return back();
328
    }
329
330
    //Show home message for edit
331
    public function showSite()
332
    {
333
        $message = Page::select('home_message')->first();
334
        return view('panel/site', $message);
0 ignored issues
show
Bug introduced by
It seems like $message can also be of type Illuminate\Database\Eloq...elations\HasManyThrough and Illuminate\Database\Eloq...Relations\HasOneThrough; however, parameter $data of view() does only seem to accept Illuminate\Contracts\Support\Arrayable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

334
        return view('panel/site', /** @scrutinizer ignore-type */ $message);
Loading history...
335
    }
336
337
    //Save home message, logo and favicon
338
    public function editSite(request $request)
339
    {
340
        $message = $request->message;
341
        $logo = $request->file('image');
342
        $icon = $request->file('icon');
343
344
        Page::first()->update(['home_message' => $message]);
345
346
        if (!empty($logo)) {
347
            // Delete existing image
348
            $path = findFile('avatar');
349
            $path = base_path('/assets/linkstack/images/'.$path);
350
    
351
                // Delete existing image
352
                if (File::exists($path)) {
353
                    File::delete($path);
354
                }
355
356
            $logo->move(base_path('/assets/linkstack/images/'), "avatar" . '_' . time() . "." .$request->file('image')->extension());
357
        }
358
359
        if (!empty($icon)) {
360
            // Delete existing image
361
            $path = findFile('favicon');
362
            $path = base_path('/assets/linkstack/images/'.$path);
363
    
364
                // Delete existing image
365
                if (File::exists($path)) {
366
                    File::delete($path);
367
                }
368
369
            $icon->move(base_path('/assets/linkstack/images/'), "favicon" . '_' . time() . "." . $request->file('icon')->extension());
370
        }
371
        return back();
372
    }
373
374
    //Delete avatar
375
    public function delAvatar()
376
    {
377
        $path = findFile('avatar');
378
        $path = base_path('/assets/linkstack/images/'.$path);
379
380
            // Delete existing image
381
            if (File::exists($path)) {
382
                File::delete($path);
383
            }
384
        
385
        return back();
386
    }
387
388
    //Delete favicon
389
    public function delFavicon()
390
    {
391
            // Delete existing image
392
            $path = findFile('favicon');
393
            $path = base_path('/assets/linkstack/images/'.$path);
394
    
395
                // Delete existing image
396
                if (File::exists($path)) {
397
                    File::delete($path);
398
                }
399
400
        return back();
401
    }
402
403
    //View footer page: terms
404
    public function pagesTerms(Request $request)
405
    {
406
        $name = "terms";
407
    
408
        try {
409
            $data['page'] = Page::select($name)->first();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
410
        } catch (Exception $e) {
411
            return abort(404);
0 ignored issues
show
Bug introduced by
Are you sure the usage of abort(404) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
412
        }
413
    
414
        return view('pages', ['data' => $data, 'name' => $name]);
415
    }
416
417
    //View footer page: privacy
418
    public function pagesPrivacy(Request $request)
419
    {
420
        $name = "privacy";
421
    
422
        try {
423
            $data['page'] = Page::select($name)->first();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
424
        } catch (Exception $e) {
425
            return abort(404);
0 ignored issues
show
Bug introduced by
Are you sure the usage of abort(404) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
426
        }
427
    
428
        return view('pages', ['data' => $data, 'name' => $name]);
429
    }
430
431
    //View footer page: contact
432
    public function pagesContact(Request $request)
433
    {
434
        $name = "contact";
435
    
436
        try {
437
            $data['page'] = Page::select($name)->first();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
438
        } catch (Exception $e) {
439
            return abort(404);
0 ignored issues
show
Bug introduced by
Are you sure the usage of abort(404) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
440
        }
441
    
442
        return view('pages', ['data' => $data, 'name' => $name]);
443
    }
444
445
    //Statistics of the number of clicks and links
446
    public function phpinfo()
447
    {
448
        return view('panel/phpinfo');
449
    }
450
451
    //Shows config file editor page
452
    public function showFileEditor(request $request)
453
    {
454
        return redirect('/admin/config');
455
    }
456
457
    //Saves advanced config
458
    public function editAC(request $request)
459
    {
460
        if ($request->ResetAdvancedConfig == 'RESET_DEFAULTS') {
461
            copy(base_path('storage/templates/advanced-config.php'), base_path('config/advanced-config.php')); 
462
        } else {
463
            file_put_contents('config/advanced-config.php', $request->AdvancedConfig);
464
        }
465
466
        return redirect('/admin/config#2');
467
    }
468
469
    //Saves .env config
470
    public function editENV(request $request)
471
    {
472
        $config = $request->altConfig;
473
474
        file_put_contents('.env', $config);
475
476
        return Redirect('/admin/config?alternative-config');
477
    }
478
479
    //Shows config file editor page
480
    public function showBackups(request $request)
481
    {
482
        return view('/panel/backups');
483
    }
484
485
    //Delete custom theme
486
    public function deleteTheme(request $request)
487
    {
488
489
        $del = $request->deltheme;
490
491
        if (empty($del)) {
492
            echo '<script type="text/javascript">';
493
            echo 'alert("No themes to delete!");';
494
            echo 'window.location.href = "../studio/theme";';
495
            echo '</script>';
496
        } else {
497
498
            $folderName = base_path() . '/themes/' . $del;
499
500
501
502
            function removeFolder($folderName)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
503
            {
504
                if (File::exists($folderName)) {
505
                    File::deleteDirectory($folderName);
506
                    return true;
507
                }
508
            
509
                return false;
510
            }
511
512
            removeFolder($folderName);
513
514
            return Redirect('/admin/theme');
515
        }
516
    }
517
518
    // Update themes
519
    public function updateThemes()
520
    {
521
522
523
        if ($handle = opendir('themes')) {
524
            while (false !== ($entry = readdir($handle))) {
525
526
                if (file_exists(base_path('themes') . '/' . $entry . '/readme.md')) {
527
                    $text = file_get_contents(base_path('themes') . '/' . $entry . '/readme.md');
528
                    $pattern = '/Theme Version:.*/';
529
                    preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE);
530
                    if (!count($matches)) continue;
531
                    $verNr = substr($matches[0][0], 15);
532
533
                }
534
535
536
                $themeVe = NULL;
537
538
                if ($entry != "." && $entry != "..") {
539
                    if (file_exists(base_path('themes') . '/' . $entry . '/readme.md')) {
540
                        if (!strpos(file_get_contents(base_path('themes') . '/' . $entry . '/readme.md'), 'Source code:')) {
541
                            $hasSource = false;
542
                        } else {
543
                            $hasSource = true;
544
545
                            $text = file_get_contents(base_path('themes') . '/' . $entry . '/readme.md');
546
                            $pattern = '/Source code:.*/';
547
                            preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE);
548
                            $sourceURL = substr($matches[0][0], 13);
549
550
                            $replaced = str_replace("https://github.com/", "https://raw.githubusercontent.com/", trim($sourceURL));
551
                            $replaced = $replaced . "/main/readme.md";
552
553
                            if (strpos($sourceURL, 'github.com')) {
554
555
                                ini_set('user_agent', 'Mozilla/4.0 (compatible; MSIE 6.0)');
556
                                try {
557
                                    $textGit = file_get_contents($replaced);
558
                                    $patternGit = '/Theme Version:.*/';
559
                                    preg_match($patternGit, $textGit, $matches, PREG_OFFSET_CAPTURE);
560
                                    $sourceURLGit = substr($matches[0][0], 15);
561
                                    $Vgitt = 'v' . $sourceURLGit;
562
                                    $verNrv = 'v' . $verNr;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $verNr does not seem to be defined for all execution paths leading up to this point.
Loading history...
563
                                } catch (Exception $ex) {
564
                                    $themeVe = "error";
0 ignored issues
show
Unused Code introduced by
The assignment to $themeVe is dead and can be removed.
Loading history...
565
                                    $Vgitt = NULL;
566
                                    $verNrv = NULL;
567
                                }
568
569
                                if (trim($Vgitt) > trim($verNrv)) {
0 ignored issues
show
Bug introduced by
It seems like $Vgitt can also be of type null; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

569
                                if (trim(/** @scrutinizer ignore-type */ $Vgitt) > trim($verNrv)) {
Loading history...
570
571
572
                                    $fileUrl = trim($sourceURL) . '/archive/refs/tags/' . trim($Vgitt) . '.zip';
573
574
575
                                    file_put_contents(base_path('themes/theme.zip'), fopen($fileUrl, 'r'));
576
577
578
                                    $zip = new ZipArchive;
579
                                    $zip->open(base_path() . '/themes/theme.zip');
580
                                    $zip->extractTo(base_path('themes'));
581
                                    $zip->close();
582
                                    unlink(base_path() . '/themes/theme.zip');
583
584
                                    $folder = base_path('themes');
585
                                    $regex = '/[0-9.-]/';
586
                                    $files = scandir($folder);
587
588
                                    foreach ($files as $file) {
589
                                        if ($file !== '.' && $file !== '..') {
590
                                            if (preg_match($regex, $file)) {
591
                                                $new_file = preg_replace($regex, '', $file);
592
                                                File::copyDirectory($folder . '/' . $file, $folder . '/' . $new_file);
593
                                                $dirname = $folder . '/' . $file;
594
                                                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
595
                                                    system('rmdir ' . escapeshellarg($dirname) . ' /s /q');
596
                                                } else {
597
                                                    system("rm -rf " . escapeshellarg($dirname));
598
                                                }
599
                                            }
600
                                        }
601
                                    }
602
                                }
603
                            }
604
                        }
605
                    }
606
                }
607
            }
608
        }
609
610
        return Redirect('/studio/theme');
611
    }
612
613
    //Shows config file editor page
614
    public function showConfig(request $request)
615
    {
616
        return view('/panel/config-editor');
617
    }
618
619
    //Shows config file editor page
620
    public function editConfig(request $request)
621
    {
622
623
        $type = $request->type;
624
        $entry = $request->entry;
625
        $value = $request->value;
626
627
        if($type === "toggle"){
628
            if($request->toggle != ''){$value = "true";}else{$value = "false";}
629
            if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);}
630
        } elseif($type === "toggle2") {
631
            if($request->toggle != ''){$value = "verified";}else{$value = "auth";}
632
            if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);}
633
        } elseif($type === "text") {
634
            if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, '"' . $value . '"');}
635
        } elseif($type === "debug") {
636
            if($request->toggle != ''){
637
                if(EnvEditor::keyExists('APP_DEBUG')){EnvEditor::editKey('APP_DEBUG', 'true');}
638
                if(EnvEditor::keyExists('APP_ENV')){EnvEditor::editKey('APP_ENV', 'local');}
639
                if(EnvEditor::keyExists('LOG_LEVEL')){EnvEditor::editKey('LOG_LEVEL', 'debug');}
640
            } else {
641
                if(EnvEditor::keyExists('APP_DEBUG')){EnvEditor::editKey('APP_DEBUG', 'false');}
642
                if(EnvEditor::keyExists('APP_ENV')){EnvEditor::editKey('APP_ENV', 'production');}
643
                if(EnvEditor::keyExists('LOG_LEVEL')){EnvEditor::editKey('LOG_LEVEL', 'error');}
644
            }
645
        } elseif($type === "register") {
646
            if($request->toggle != ''){$register = "true";}else{$register = "false";}
647
            Page::first()->update(['register' => $register]);
648
        } elseif($type === "smtp") {
649
            if($request->toggle != ''){$value = "built-in";}else{$value = "smtp";}
650
            if(EnvEditor::keyExists('MAIL_MAILER')){EnvEditor::editKey('MAIL_MAILER', $value);}
651
652
            if(EnvEditor::keyExists('MAIL_HOST')){EnvEditor::editKey('MAIL_HOST', $request->MAIL_HOST);}
653
            if(EnvEditor::keyExists('MAIL_PORT')){EnvEditor::editKey('MAIL_PORT', $request->MAIL_PORT);}
654
            if(EnvEditor::keyExists('MAIL_USERNAME')){EnvEditor::editKey('MAIL_USERNAME', '"' . $request->MAIL_USERNAME . '"');}
655
            if(EnvEditor::keyExists('MAIL_PASSWORD')){EnvEditor::editKey('MAIL_PASSWORD', '"' . $request->MAIL_PASSWORD . '"');}
656
            if(EnvEditor::keyExists('MAIL_ENCRYPTION')){EnvEditor::editKey('MAIL_ENCRYPTION', $request->MAIL_ENCRYPTION);}
657
            if(EnvEditor::keyExists('MAIL_FROM_ADDRESS')){EnvEditor::editKey('MAIL_FROM_ADDRESS', $request->MAIL_FROM_ADDRESS);}
658
        } elseif($type === "homeurl") {
659
            if($request->value == 'default'){$value = "";}else{$value = '"' . $request->value . '"';}
660
            if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);}
661
        } elseif($type === "maintenance") {
662
            if($request->toggle != ''){$value = "true";}else{$value = "false";}
663
            if(file_exists(base_path("storage/MAINTENANCE"))){unlink(base_path("storage/MAINTENANCE"));}
664
            if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);}
665
        } else {
666
            if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);}
667
        }
668
669
670
671
672
        return Redirect('/admin/config');
673
    }
674
    
675
    //Shows theme editor page
676
    public function showThemes(request $request)
677
    {
678
        return view('/panel/theme');
679
    }
680
681
    //Removes impersonation if authenticated
682
    public function authAs(request $request)
683
    {
684
685
        $userID = $request->id;
686
        $token = $request->token;
687
688
        $user = User::find($userID);
689
690
        if($user->remember_token == $token && $request->session()->get('display_auth_nav') === $user->remember_token){
691
            $user->auth_as = null;
692
            $user->remember_token = null;
693
            $user->save();
694
695
            $request->session()->forget('display_auth_nav');
696
697
            Auth::loginUsingId($userID);
698
699
        return redirect('/admin/users/all');
700
        } else {
701
            Auth::logout();
702
        }
703
704
    }
705
706
    //Add impersonation
707
    public function authAsID(request $request)
708
    {
709
710
        $adminUser = User::whereNotNull('auth_as')->where('role', 'admin')->first();
711
712
        if (!$adminUser) {
713
714
        $userID = $request->id;
715
        $id = Auth::user()->id;
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
716
717
        $user = User::find($id);
718
719
        $user->auth_as = $userID;
720
        $user->save();
721
722
        return redirect('dashboard');
723
724
        } else {
725
            return redirect('admin/users/all');
726
        }
727
728
    }
729
730
    //Show info about link
731
    public function redirectInfo(request $request)
732
    {
733
        $linkId = $request->id;
734
735
        if (empty($linkId)) {
736
            return abort(404);
0 ignored issues
show
Bug introduced by
Are you sure the usage of abort(404) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
737
        }
738
        
739
        $linkData = Link::find($linkId);
740
        $clicks = $linkData->click_number;
741
742
        if (empty($linkData)) {
743
            return abort(404);
0 ignored issues
show
Bug introduced by
Are you sure the usage of abort(404) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
744
        }
745
746
        function isValidLink($url) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
747
            $validPrefixes = array('http', 'https', 'ftp', 'mailto', 'tel', 'news');
748
        
749
            $pattern = '/^(' . implode('|', $validPrefixes) . '):/i';
750
        
751
            if (preg_match($pattern, $url) && strlen($url) <= 155) {
752
                return $url;
753
            } else {
754
                return "N/A";
755
            }
756
        }
757
758
        $link = isValidLink($linkData->link);
759
760
        $userID = $linkData->user_id;
761
        $userData = User::find($userID);
762
763
        return view('linkinfo', ['clicks' => $clicks, 'linkID' => $linkId, 'link' => $link, 'id' => $userID, 'userData' => $userData]);
764
765
    }
766
767
}
768