Passed
Push — main ( cab5e4...1abab3 )
by Julian
04:52
created

UserController   F

Complexity

Total Complexity 131

Size/Duplication

Total Lines 1024
Duplicated Lines 0 %

Importance

Changes 24
Bugs 1 Features 0
Metric Value
eloc 536
c 24
b 1
f 0
dl 0
loc 1024
rs 2
wmc 131

36 Methods

Rating   Name   Duplication   Size   Complexity  
A index() 0 29 1
A AddUpdateLink() 0 15 2
B littlelink() 0 44 8
A littlelinkhome() 0 15 2
A userRedirect() 0 14 3
B editPage() 0 76 10
A clearIcon() 0 14 5
A editProfile() 0 23 4
A removeBackground() 0 11 2
A editLink() 0 26 5
F importData() 0 99 12
A delProfilePicture() 0 11 2
A editIcons() 0 27 5
A deleteUser() 0 20 3
A showLinks() 0 7 1
A updateIcon() 0 6 1
B sortLinks() 0 35 6
A showTheme() 0 7 1
A searchIcon() 0 7 1
A editCSS() 0 14 5
B editTheme() 0 51 7
A report() 0 10 2
A theme() 0 15 2
A showLink() 0 14 1
A showProfile() 0 7 1
A deleteLink() 0 16 5
A addIcon() 0 11 1
B themeBackground() 0 46 6
A exportAll() 0 33 3
A clickNumber() 0 27 4
C saveLink() 0 80 12
A showCSS() 0 14 1
A exportLinks() 0 23 2
A upLink() 0 14 3
A vcard() 0 45 1
A showPage() 0 7 1

How to fix   Complexity   

Complex Class

Complex classes like UserController 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 UserController, 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 Cohensive\OEmbed\Facades\OEmbed;
8
use Illuminate\Support\Facades\Schema;
9
use Illuminate\Support\Facades\Route;
10
use Illuminate\Support\Facades\Response;
11
use JeroenDesloovere\VCard\VCard;
12
use Illuminate\Validation\Rule;
13
use Illuminate\Support\Facades\Validator;
14
use Illuminate\Support\Facades\Mail;
15
use App\Mail\ReportSubmissionMail;
16
use GeoSot\EnvEditor\Facades\EnvEditor;
17
18
use Auth;
19
use DB;
20
use ZipArchive;
21
use File;
22
23
use App\Models\User;
24
use App\Models\Button;
25
use App\Models\Link;
26
use App\Models\LinkType;
27
use App\Models\UserData;
28
29
30
//Function tests if string starts with certain string (used to test for illegal strings)
31
function stringStartsWith($haystack, $needle, $case = true)
32
{
33
    if ($case) {
34
        return strpos($haystack, $needle, 0) === 0;
35
    }
36
    return stripos($haystack, $needle, 0) === 0;
37
}
38
39
//Function tests if string ends with certain string (used to test for illegal strings)
40
function stringEndsWith($haystack, $needle, $case = true)
41
{
42
    $expectedPosition = strlen($haystack) - strlen($needle);
43
    if ($case) {
44
        return strrpos($haystack, $needle, 0) === $expectedPosition;
45
    }
46
    return strripos($haystack, $needle, 0) === $expectedPosition;
47
}
48
49
class UserController extends Controller
50
{
51
52
    //Statistics of the number of clicks and links
53
    public function index()
54
    {
55
        $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...
56
57
        $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...
58
        $userinfo = User::find($userId);
59
60
        $links = Link::where('user_id', $userId)->select('link')->count();
61
        $clicks = Link::where('user_id', $userId)->sum('click_number');
62
        $topLinks = Link::where('user_id', $userId)->orderby('click_number', 'desc')
63
            ->whereNotNull('link')->where('link', '<>', '')
64
            ->take(5)->get();
65
66
        $pageStats = [
67
            'visitors' => [
68
                'all' => visits('App\Models\User', $littlelink_name)->count(),
69
                'day' => visits('App\Models\User', $littlelink_name)->period('day')->count(),
70
                'week' => visits('App\Models\User', $littlelink_name)->period('week')->count(),
71
                'month' => visits('App\Models\User', $littlelink_name)->period('month')->count(),
72
                'year' => visits('App\Models\User', $littlelink_name)->period('year')->count(),
73
            ],
74
            'os' => visits('App\Models\User', $littlelink_name)->operatingSystems(),
75
            'referers' => visits('App\Models\User', $littlelink_name)->refs(),
76
            'countries' => visits('App\Models\User', $littlelink_name)->countries(),
77
        ];
78
79
80
81
        return view('studio/index', ['greeting' => $userinfo->name, 'toplinks' => $topLinks, 'links' => $links, 'clicks' => $clicks, 'pageStats' => $pageStats]);
82
    }
83
84
    //Show littlelink page. example => http://127.0.0.1:8000/+admin
85
    public function littlelink(request $request)
86
    {
87
        if(isset($request->useif)){
88
            $littlelink_name = User::select('littlelink_name')->where('id', $request->littlelink)->value('littlelink_name');
89
            $id = $request->littlelink;
90
        } else {
91
            $littlelink_name = $request->littlelink;
92
            $id = User::select('id')->where('littlelink_name', $littlelink_name)->value('id');
93
        }
94
95
        if (empty($id)) {
96
            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...
97
        }
98
     
99
        $userinfo = User::select('id', 'name', 'littlelink_name', 'littlelink_description', 'theme', 'role', 'block')->where('id', $id)->first();
100
        $information = User::select('name', 'littlelink_name', 'littlelink_description', 'theme')->where('id', $id)->get();
101
        
102
        if ($userinfo->block == 'yes') {
0 ignored issues
show
Bug introduced by
The property block does not seem to exist on Illuminate\Database\Eloq...Relations\HasOneThrough.
Loading history...
Bug introduced by
The property block does not seem to exist on Illuminate\Database\Eloq...elations\HasManyThrough.
Loading history...
103
            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...
104
        }
105
        
106
        $links = DB::table('links')
107
        ->join('buttons', 'buttons.id', '=', 'links.button_id')
108
        ->select('links.*', 'buttons.name') // Assuming 'links.*' to fetch all columns including 'type_params'
109
        ->where('user_id', $id)
110
        ->orderBy('up_link', 'asc')
111
        ->orderBy('order', 'asc')
112
        ->get();
113
114
        // Loop through each link to decode 'type_params' and merge it into the link object
115
        foreach ($links as $link) {
116
            if (!empty($link->type_params)) {
117
                // Decode the JSON string into an associative array
118
                $typeParams = json_decode($link->type_params, true);
119
                if (is_array($typeParams)) {
120
                    // Merge the associative array into the link object
121
                    foreach ($typeParams as $key => $value) {
122
                        $link->$key = $value;
123
                    }
124
                }
125
            }
126
        }
127
128
        return view('linkstack.linkstack', ['userinfo' => $userinfo, 'information' => $information, 'links' => $links, 'littlelink_name' => $littlelink_name]);
129
    }
130
131
    //Show littlelink page as home page if set in config
132
    public function littlelinkhome(request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

132
    public function littlelinkhome(/** @scrutinizer ignore-unused */ request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
133
    {
134
        $littlelink_name = env('HOME_URL');
135
        $id = User::select('id')->where('littlelink_name', $littlelink_name)->value('id');
136
137
        if (empty($id)) {
138
            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...
139
        }
140
     
141
        $userinfo = User::select('id', 'name', 'littlelink_name', 'littlelink_description', 'theme', 'role', 'block')->where('id', $id)->first();
142
        $information = User::select('name', 'littlelink_name', 'littlelink_description', 'theme')->where('id', $id)->get();
143
        
144
        $links = DB::table('links')->join('buttons', 'buttons.id', '=', 'links.button_id')->select('links.link', 'links.id', 'links.button_id', 'links.title', 'links.custom_css', 'links.custom_icon', 'buttons.name')->where('user_id', $id)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->get();
145
146
        return view('linkstack.linkstack', ['userinfo' => $userinfo, 'information' => $information, 'links' => $links, 'littlelink_name' => $littlelink_name]);
147
    }
148
149
    //Redirect to user page
150
    public function userRedirect(request $request)
151
    {
152
        $id = $request->id;
153
        $user = User::select('littlelink_name')->where('id', $id)->value('littlelink_name');
154
155
        if (empty($id)) {
156
            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...
157
        }
158
     
159
        if (empty($user)) {
160
            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...
161
        }
162
163
        return redirect(url('@'.$user));
164
    }
165
166
    //Show add/update form
167
    public function AddUpdateLink($id = 0)
168
    {
169
        $linkData = $id ? Link::find($id) : new Link(['typename' => 'link', 'id' => '0']);
170
    
171
        $data = [
172
            'LinkTypes' => LinkType::get(),
173
            'LinkData' => $linkData,
174
            'LinkID' => $id,
175
            'linkTypeID' => "predefined",
176
            'title' => "Predefined Site",
177
        ];
178
179
        $data['typename'] = $linkData->type ?? 'predefined';
180
    
181
        return view('studio/edit-link', $data);
182
    }
183
184
    //Save add link
185
    public function saveLink(Request $request)
186
    {
187
        // Step 1: Validate Request
188
        // $request->validate([
189
        //     'link' => 'sometimes|url',
190
        // ]);
191
    
192
        // Step 2: Determine Link Type and Title
193
        $linkType = LinkType::findByTypename($request->typename);
194
        $LinkTitle = $request->title;
195
        $LinkURL = $request->link;
196
197
        // Step 3: Load Link Type Logic
198
        if($request->typename == 'predefined' || $request->typename == 'link') {
199
            // Determine button id based on whether a custom or predefined button is used
200
            $button_id = ($request->typename == 'link') ? ($request->GetSiteIcon == 1 ? 2 : 1) : null;
201
            $button = ($request->typename != 'link') ? Button::where('name', $request->button)->first() : null;
202
203
            $linkData = [
204
                'link' => $LinkURL,
205
                'title' => $LinkTitle ?? $button?->alt,
0 ignored issues
show
Bug introduced by
The property alt does not seem to exist on Illuminate\Database\Eloq...Relations\HasOneThrough.
Loading history...
Bug introduced by
The property alt does not seem to exist on Illuminate\Database\Eloq...elations\HasManyThrough.
Loading history...
206
                'user_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...
207
                'button_id' => $button?->id ?? $button_id,
0 ignored issues
show
Bug introduced by
The property id does not seem to exist on Illuminate\Database\Eloq...Relations\HasOneThrough.
Loading history...
Bug introduced by
The property id does not seem to exist on Illuminate\Database\Eloq...elations\HasManyThrough.
Loading history...
208
                'type' => $request->typename // Save the link type
209
            ];
210
        } else {
211
            $linkTypePath = base_path("blocks/{$linkType->typename}/handler.php");
0 ignored issues
show
Bug introduced by
The property typename does not seem to exist on App\Models\LinkType. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
212
            if (file_exists($linkTypePath)) {
213
                include $linkTypePath;
214
                $linkData = handleLinkType($request, $linkType);
215
                $linkData['button_id'] = $linkData['button_id'] ?? 1; // Set 'button_id' unless overwritten by handleLinkType
216
                $linkData['type'] = $linkType->typename; // Ensure 'type' is included in $linkData
217
            } else {
218
                abort(404, "Link type logic not found.");
219
            }
220
        }   
221
222
        // Step 4: Handle Custom Parameters
223
        // (Same as before)
224
225
        // Step 5: User and Button Information
226
        $userId = Auth::user()->id;
227
        $button = Button::where('name', $request->button)->first();
228
        if ($button && empty($LinkTitle)) $LinkTitle = $button->alt;
0 ignored issues
show
Unused Code introduced by
The assignment to $LinkTitle is dead and can be removed.
Loading history...
229
230
        // Step 6: Prepare Link Data
231
        // (Handled by the included file)
232
233
        // Step 7: Save or Update Link
234
        $OrigLink = Link::find($request->linkid);
235
        $linkColumns = Schema::getColumnListing('links'); // Get all column names of links table
236
        $filteredLinkData = array_intersect_key($linkData, array_flip($linkColumns)); // Filter $linkData to only include keys that are columns in the links table
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $linkData does not seem to be defined for all execution paths leading up to this point.
Loading history...
237
238
        // Combine remaining variables into one array and convert to JSON for the type_params column
239
        $customParams = array_diff_key($linkData, $filteredLinkData);
240
241
            // Check if $linkType->custom_html is defined and not null
242
            if (isset($linkType->custom_html)) {
243
                // Add $linkType->custom_html to the $customParams array
244
                $customParams['custom_html'] = $linkType->custom_html;
0 ignored issues
show
Bug introduced by
The property custom_html does not seem to exist on App\Models\LinkType. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
245
            }
246
        
247
        $filteredLinkData['type_params'] = json_encode($customParams);
248
249
        if ($OrigLink) {
250
            $currentValues = $OrigLink->getAttributes();
251
            $nonNullFilteredLinkData = array_filter($filteredLinkData, function($value) {return !is_null($value);});
252
            $updatedValues = array_merge($currentValues, $nonNullFilteredLinkData);
253
            $OrigLink->update($updatedValues);
254
            $message = "Link updated";
255
        } else {
256
            $link = new Link($filteredLinkData);
257
            $link->user_id = $userId;
258
            $link->save();
259
            $message = "Link added";
260
        }
261
262
        // Step 8: Redirect
263
        $redirectUrl = $request->input('param') == 'add_more' ? 'studio/add-link' : 'studio/links';
264
        return Redirect($redirectUrl)->with('success', $message);
265
    }
266
    
267
    public function sortLinks(Request $request)
268
    {
269
        $linkOrders  = $request->input("linkOrders", []);
270
        $currentPage = $request->input("currentPage", 1);
271
        $perPage     = $request->input("perPage", 0);
272
273
        if ($perPage == 0) {
274
            $currentPage = 1;
275
        }
276
277
        $linkOrders = array_unique(array_filter($linkOrders));
278
        if (!$linkOrders || $currentPage < 1) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $linkOrders of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
279
            return response()->json([
280
                'status' => 'ERROR',
281
            ]);
282
        }
283
284
        $newOrder = $perPage * ($currentPage - 1);
285
        $linkNewOrders = [];
286
        foreach ($linkOrders as $linkId) {
287
            if ($linkId < 0) {
288
                continue;
289
            }
290
291
            $linkNewOrders[$linkId] = $newOrder;
292
            Link::where("id", $linkId)
293
                ->update([
294
                    'order' => $newOrder
295
                ]);
296
            $newOrder++;
297
        }
298
299
        return response()->json([
300
            'status' => 'OK',
301
            'linkOrders' => $linkNewOrders,
302
        ]);
303
    }
304
305
306
    //Count the number of clicks and redirect to link
307
    public function clickNumber(request $request)
308
    {
309
        $linkId = $request->id;
310
311
        if (substr($linkId, -1) == '+') {
312
            $linkWithoutPlus = str_replace('+', '', $linkId);
313
            return redirect(url('info/'.$linkWithoutPlus));
314
        }
315
    
316
        $link = Link::find($linkId);
317
318
        if (empty($link)) {
319
            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...
320
        }
321
322
        $link = $link->link;
323
324
        if (empty($linkId)) {
325
            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...
326
        }
327
328
        Link::where('id', $linkId)->increment('click_number', 1);
329
330
        $response = redirect()->away($link);
331
        $response->header('X-Robots-Tag', 'noindex, nofollow');
332
333
        return $response;
334
    }
335
336
    //Download Vcard
337
    public function vcard(request $request)
338
    {
339
        $linkId = $request->id;
340
341
        // Find the link with the specified ID
342
        $link = Link::findOrFail($linkId);
343
344
        $json = $link->link;
345
346
        // Decode the JSON to a PHP array
347
        $data = json_decode($json, true);
348
        
349
        // Create a new vCard object
350
        $vcard = new VCard();
351
        
352
        // Set the vCard properties from the $data array
353
        $vcard->addName($data['last_name'], $data['first_name'], $data['middle_name'], $data['prefix'], $data['suffix']);
354
        $vcard->addCompany($data['organization']);
355
        $vcard->addJobtitle($data['vtitle']);
356
        $vcard->addRole($data['role']);
357
        $vcard->addEmail($data['email']);
358
        $vcard->addEmail($data['work_email'], 'WORK');
359
        $vcard->addURL($data['work_url'], 'WORK');
360
        $vcard->addPhoneNumber($data['home_phone'], 'HOME');
361
        $vcard->addPhoneNumber($data['work_phone'], 'WORK');
362
        $vcard->addPhoneNumber($data['cell_phone'], 'CELL');
363
        $vcard->addAddress($data['home_address_street'], '', $data['home_address_city'], $data['home_address_state'], $data['home_address_zip'], $data['home_address_country'], 'HOME');
364
        $vcard->addAddress($data['work_address_street'], '', $data['work_address_city'], $data['work_address_state'], $data['work_address_zip'], $data['work_address_country'], 'WORK');
365
        
366
367
        // $vcard->addPhoto(base_path('img/1.png'));
368
        
369
        // Generate the vCard file contents
370
        $file_contents = $vcard->getOutput();
371
        
372
        // Set the file headers for download
373
        $headers = [
374
            'Content-Type' => 'text/x-vcard',
375
            'Content-Disposition' => 'attachment; filename="contact.vcf"'
376
        ];
377
        
378
        Link::where('id', $linkId)->increment('click_number', 1);
379
380
        // Return the file download response
381
        return response()->make($file_contents, 200, $headers);
382
383
    }
384
385
    //Show link, click number, up link in links page
386
    public function showLinks()
387
    {
388
        $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...
389
        $data['pagePage'] = 10;
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...
390
        
391
        $data['links'] = Link::select()->where('user_id', $userId)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->paginate(99999);
392
        return view('studio/links', $data);
393
    }
394
395
    //Delete link
396
    public function deleteLink(request $request)
397
    {
398
        $linkId = $request->id;
399
400
        Link::where('id', $linkId)->delete();
401
402
        $directory = base_path("assets/favicon/icons");
403
        $files = scandir($directory);
404
        foreach($files as $file) {
405
        if (strpos($file, $linkId.".") !== false) {
406
        $pathinfo = pathinfo($file, PATHINFO_EXTENSION);}}
407
        if (isset($pathinfo)) {
408
        try{File::delete(base_path("assets/favicon/icons")."/".$linkId.".".$pathinfo);} catch (exception $e) {}
0 ignored issues
show
introduced by
Consider moving this CATCH statement to a new line.
Loading history...
Bug introduced by
The type App\Http\Controllers\exception was not found. Did you mean exception? If so, make sure to prefix the type with \.
Loading history...
409
        }
410
411
        return redirect('/studio/links');
412
    }
413
414
    //Delete icon
415
    public function clearIcon(request $request)
416
    {
417
        $linkId = $request->id;
418
419
        $directory = base_path("assets/favicon/icons");
420
        $files = scandir($directory);
421
        foreach($files as $file) {
422
        if (strpos($file, $linkId.".") !== false) {
423
        $pathinfo = pathinfo($file, PATHINFO_EXTENSION);}}
424
        if (isset($pathinfo)) {
425
        try{File::delete(base_path("assets/favicon/icons")."/".$linkId.".".$pathinfo);} catch (exception $e) {}
0 ignored issues
show
introduced by
Consider moving this CATCH statement to a new line.
Loading history...
426
        }
427
428
        return redirect('/studio/links');
429
    }
430
431
    //Raise link on the littlelink page
432
    public function upLink(request $request)
433
    {
434
        $linkId = $request->id;
435
        $upLink = $request->up;
436
437
        if ($upLink == 'yes') {
438
            $up = 'no';
439
        } elseif ($upLink == 'no') {
440
            $up = 'yes';
441
        }
442
443
        Link::where('id', $linkId)->update(['up_link' => $up]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $up does not seem to be defined for all execution paths leading up to this point.
Loading history...
444
445
        return back();
446
    }
447
448
    //Show link to edit
449
    public function showLink(request $request)
450
    {
451
        $linkId = $request->id;
452
453
        $link = Link::where('id', $linkId)->value('link');
454
        $title = Link::where('id', $linkId)->value('title');
455
        $order = Link::where('id', $linkId)->value('order');
456
        $custom_css = Link::where('id', $linkId)->value('custom_css');
457
        $buttonId = Link::where('id', $linkId)->value('button_id');
458
        $buttonName = Button::where('id', $buttonId)->value('name');
459
460
        $buttons = Button::select('id', 'name')->orderBy('name', 'asc')->get();
461
462
        return view('studio/edit-link', ['custom_css' => $custom_css, 'buttonId' => $buttonId, 'buttons' => $buttons, 'link' => $link, 'title' => $title, 'order' => $order, 'id' => $linkId, 'buttonName' => $buttonName]);
463
    }
464
465
    //Show custom CSS + custom icon
466
    public function showCSS(request $request)
467
    {
468
        $linkId = $request->id;
469
470
        $link = Link::where('id', $linkId)->value('link');
471
        $title = Link::where('id', $linkId)->value('title');
472
        $order = Link::where('id', $linkId)->value('order');
473
        $custom_css = Link::where('id', $linkId)->value('custom_css');
474
        $custom_icon = Link::where('id', $linkId)->value('custom_icon');
475
        $buttonId = Link::where('id', $linkId)->value('button_id');
476
477
        $buttons = Button::select('id', 'name')->get();
478
479
        return view('studio/button-editor', ['custom_icon' => $custom_icon, 'custom_css' => $custom_css, 'buttonId' => $buttonId, 'buttons' => $buttons, 'link' => $link, 'title' => $title, 'order' => $order, 'id' => $linkId]);
480
    }
481
482
    //Save edit link
483
    public function editLink(request $request)
484
    {
485
        $request->validate([
486
            'link' => 'required|exturl',
487
            'title' => 'required',
488
            'button' => 'required',
489
        ]);
490
491
        if (stringStartsWith($request->link, 'http://') == 'true' or stringStartsWith($request->link, 'https://') == 'true' or stringStartsWith($request->link, 'mailto:') == 'true')
492
            $link1 = $request->link;
493
        else
494
            $link1 = 'https://' . $request->link;
495
        if (stringEndsWith($request->link, '/') == 'true')
496
            $link = rtrim($link1, "/ ");
497
        else
498
        $link = $link1;
499
        $title = $request->title;
500
        $order = $request->order;
501
        $button = $request->button;
502
        $linkId = $request->id;
503
504
        $buttonId = Button::select('id')->where('name', $button)->value('id');
505
506
        Link::where('id', $linkId)->update(['link' => $link, 'title' => $title, 'order' => $order, 'button_id' => $buttonId]);
507
508
        return redirect('/studio/links');
509
    }
510
511
    //Save edit custom CSS + custom icon
512
    public function editCSS(request $request)
513
    {
514
        $linkId = $request->id;
515
        $custom_icon = $request->custom_icon;
516
        $custom_css = $request->custom_css;
517
518
        if ($request->custom_css == "" and $request->custom_icon = !"") {
0 ignored issues
show
Bug introduced by
The property custom_icon does not seem to exist on Illuminate\Http\Request.
Loading history...
519
            Link::where('id', $linkId)->update(['custom_icon' => $custom_icon]);
520
        } elseif ($request->custom_icon == "" and $request->custom_css = !"") {
0 ignored issues
show
Bug introduced by
The property custom_css does not seem to exist on Illuminate\Http\Request.
Loading history...
521
            Link::where('id', $linkId)->update(['custom_css' => $custom_css]);
522
        } else {
523
            Link::where('id', $linkId)->update([]);
524
        }
525
        return Redirect('#result');
526
    }
527
528
    //Show littlelinke page for edit
529
    public function showPage(request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

529
    public function showPage(/** @scrutinizer ignore-unused */ request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
530
    {
531
        $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...
532
533
        $data['pages'] = User::where('id', $userId)->select('littlelink_name', 'littlelink_description', 'image', 'name')->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...
534
535
        return view('/studio/page', $data);
536
    }
537
538
    //Save littlelink page (name, description, logo)
539
    public function editPage(Request $request)
540
    {
541
        $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...
542
        $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...
543
    
544
        $validator = Validator::make($request->all(), [
545
            'littlelink_name' => [
546
                'sometimes',
547
                'max:255',
548
                'string',
549
                'isunique:users,id,'.$userId,
550
            ],
551
            'name' => 'sometimes|max:255|string',
552
            'image' => 'sometimes|image|mimes:jpeg,jpg,png,webp|max:2048', // Max file size: 2MB
553
        ], [
554
            'littlelink_name.unique' => __('messages.That handle has already been taken'),
555
            'image.image' => __('messages.The selected file must be an image'),
556
            'image.mimes' => __('messages.The image must be') . ' JPEG, JPG, PNG, webP.',
557
            'image.max' => __('messages.The image size should not exceed 2MB'),
558
        ]);
559
    
560
        if ($validator->fails()) {
561
            return redirect('/studio/page')->withErrors($validator)->withInput();
562
        }
563
    
564
        $profilePhoto = $request->file('image');
565
        $pageName = $request->littlelink_name;
566
        $pageDescription = strip_tags($request->pageDescription, '<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
567
        $pageDescription = preg_replace("/<a([^>]*)>/i", "<a $1 rel=\"noopener noreferrer nofollow\">", $pageDescription);
568
        $pageDescription = strip_tags_except_allowed_protocols($pageDescription);
569
        $name = $request->name;
570
        $checkmark = $request->checkmark;
571
        $sharebtn = $request->sharebtn;
572
        $tablinks = $request->tablinks;
573
574
        if(env('HOME_URL') !== '' && $pageName != $littlelink_name && $littlelink_name == env('HOME_URL')){
575
            EnvEditor::editKey('HOME_URL', $pageName);
576
        }
577
    
578
        User::where('id', $userId)->update([
579
            'littlelink_name' => $pageName,
580
            'littlelink_description' => $pageDescription,
581
            'name' => $name
582
        ]);
583
    
584
        if ($request->hasFile('image')) {
585
586
            // Delete the user's current avatar if it exists
587
            while (findAvatar($userId) !== "error.error") {
588
                $avatarName = findAvatar($userId);
589
                unlink(base_path($avatarName));
590
            }
591
            
592
            $fileName = $userId . '_' . time() . "." . $profilePhoto->extension();
593
            $profilePhoto->move(base_path('assets/img'), $fileName);
594
        }
595
    
596
        if ($checkmark == "on") {
597
            UserData::saveData($userId, 'checkmark', true);
598
        } else {
599
            UserData::saveData($userId, 'checkmark', false);
600
        }
601
    
602
        if ($sharebtn == "on") {
603
            UserData::saveData($userId, 'disable-sharebtn', false);
604
        } else {
605
            UserData::saveData($userId, 'disable-sharebtn', true);
606
        }
607
608
        if ($tablinks == "on") {
609
            UserData::saveData($userId, 'links-new-tab', true);
610
        } else {
611
            UserData::saveData($userId, 'links-new-tab', false);
612
        }
613
    
614
        return Redirect('/studio/page');
615
    }
616
617
    //Upload custom theme background image
618
    public function themeBackground(Request $request)
619
    {
620
        $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...
621
        $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...
Unused Code introduced by
The assignment to $littlelink_name is dead and can be removed.
Loading history...
622
    
623
        $request->validate([
624
            'image' => 'required|image|mimes:jpeg,jpg,png,webp,gif|max:2048', // Max file size: 2MB
625
        ], [
626
            'image.required' => __('messages.Please select an image'),
627
            'image.image' => __('messages.The selected file must be an image'),
628
            'image.mimes' => __('messages.The image must be') . ' JPEG, JPG, PNG, webP, GIF.',
629
            'image.max' => __('messages.The image size should not exceed 2MB'),
630
        ]);
631
    
632
        $customBackground = $request->file('image');
633
    
634
        if ($customBackground) {
635
            $directory = base_path('assets/img/background-img/');
636
            $files = scandir($directory);
637
            $pathinfo = "error.error";
0 ignored issues
show
Unused Code introduced by
The assignment to $pathinfo is dead and can be removed.
Loading history...
638
            foreach ($files as $file) {
639
                if (strpos($file, $userId . '.') !== false) {
640
                    $pathinfo = $userId . "." . 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

640
                    $pathinfo = $userId . "." . /** @scrutinizer ignore-type */ pathinfo($file, PATHINFO_EXTENSION);
Loading history...
641
                }
642
            }
643
    
644
            // Delete the user's current background image if it exists
645
            while (findBackground($userId) !== "error.error") {
646
                $avatarName = "assets/img/background-img/" . findBackground(Auth::id());
647
                unlink(base_path($avatarName));
648
            }
649
                
650
            $fileName = $userId . '_' . time() . "." . $customBackground->extension();
651
            $customBackground->move(base_path('assets/img/background-img/'), $fileName);
652
    
653
            if (extension_loaded('imagick')) {
654
                $imagePath = base_path('assets/img/background-img/') . $fileName;
655
                $image = new \Imagick($imagePath);
656
                $image->stripImage();
657
                $image->writeImage($imagePath);
658
            }
659
    
660
            return redirect('/studio/theme');
661
        }
662
    
663
        return redirect('/studio/theme')->with('error', 'Please select a valid image file.');
664
    }
665
666
    //Delete custom background image
667
    public function removeBackground()
668
    {
669
        $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...
670
671
        // Delete the user's current background image if it exists
672
        while (findBackground($userId) !== "error.error") {
673
            $avatarName = "assets/img/background-img/" . findBackground(Auth::id());
674
            unlink(base_path($avatarName));
675
        }
676
677
        return back();
678
    }
679
680
681
    //Show custom theme
682
    public function showTheme(request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

682
    public function showTheme(/** @scrutinizer ignore-unused */ request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
683
    {
684
        $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...
685
686
        $data['pages'] = User::where('id', $userId)->select('littlelink_name', 'theme')->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...
687
688
        return view('/studio/theme', $data);
689
    }
690
691
    //Save custom theme
692
    public function editTheme(request $request)
693
    {
694
        $request->validate([
695
            'zip' => 'sometimes|mimes:zip',
696
        ]);
697
698
        $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...
699
700
        $zipfile = $request->file('zip');
701
702
        $theme = $request->theme;
703
        $message = "";
704
705
        User::where('id', $userId)->update(['theme' => $theme]);
706
707
708
709
        if (!empty($zipfile)) {
710
711
            $zipfile->move(base_path('/themes'), "temp.zip");
712
713
            $zip = new ZipArchive;
714
            $zip->open(base_path() . '/themes/temp.zip');
715
            $zip->extractTo(base_path() . '/themes');
716
            $zip->close();
717
            unlink(base_path() . '/themes/temp.zip');
718
719
            // Removes version numbers from folder.
720
721
            $folder = base_path('themes');
722
            $regex = '/[0-9.-]/';
723
            $files = scandir($folder);
724
725
            foreach ($files as $file) {
726
                if ($file !== '.' && $file !== '..') {
727
                    if (preg_match($regex, $file)) {
728
                        $new_file = preg_replace($regex, '', $file);
729
                        File::copyDirectory($folder . '/' . $file, $folder . '/' . $new_file);
730
                        $dirname = $folder . '/' . $file;
731
                        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
732
                            system('rmdir ' . escapeshellarg($dirname) . ' /s /q');
733
                        } else {
734
                            system("rm -rf " . escapeshellarg($dirname));
735
                        }
736
                    }
737
                }
738
            }
739
        }
740
741
742
        return Redirect('/studio/theme')->with("success", $message);
743
    }
744
745
    //Show user (name, email, password)
746
    public function showProfile(request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

746
    public function showProfile(/** @scrutinizer ignore-unused */ request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
747
    {
748
        $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...
749
750
        $data['profile'] = User::where('id', $userId)->select('name', 'email', 'role')->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...
751
752
        return view('/studio/profile', $data);
753
    }
754
755
    //Save user (name, email, password)
756
    public function editProfile(request $request)
757
    {
758
        $request->validate([
759
            'name' => 'sometimes|required|unique:users',
760
            'email' => 'sometimes|required|email|unique:users',
761
            'password' => 'sometimes|min:8',
762
        ]);
763
764
        $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...
765
766
        $name = $request->name;
767
        $email = $request->email;
768
        $password = Hash::make($request->password);
769
770
        if ($request->name != '') {
771
            User::where('id', $userId)->update(['name' => $name]);
772
        } elseif ($request->email != '') {
773
            User::where('id', $userId)->update(['email' => $email]);
774
        } elseif ($request->password != '') {
775
            User::where('id', $userId)->update(['password' => $password]);
776
            Auth::logout();
777
        }
778
        return back();
779
    }
780
781
    //Show user theme credit page
782
    public function theme(request $request)
783
    {
784
        $littlelink_name = $request->littlelink;
785
        $id = User::select('id')->where('littlelink_name', $littlelink_name)->value('id');
786
787
        if (empty($id)) {
788
            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...
789
        }
790
791
        $userinfo = User::select('name', 'littlelink_name', 'littlelink_description', 'theme')->where('id', $id)->first();
792
        $information = User::select('name', 'littlelink_name', 'littlelink_description', 'theme')->where('id', $id)->get();
793
794
        $links = DB::table('links')->join('buttons', 'buttons.id', '=', 'links.button_id')->select('links.link', 'links.id', 'links.button_id', 'links.title', 'links.custom_css', 'links.custom_icon', 'buttons.name')->where('user_id', $id)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->get();
795
796
        return view('components/theme', ['userinfo' => $userinfo, 'information' => $information, 'links' => $links, 'littlelink_name' => $littlelink_name]);
797
    }
798
799
    //Delete existing user
800
    public function deleteUser(request $request)
801
    {
802
803
        // echo $request->id;
804
        // echo "<br>";
805
        // echo Auth::id();
806
        $id = $request->id;
807
808
    if($id == Auth::id() and $id != "1") {
809
810
        Link::where('user_id', $id)->delete();
811
812
        $user = User::find($id);
813
814
        Schema::disableForeignKeyConstraints();
815
        $user->forceDelete();
816
        Schema::enableForeignKeyConstraints();
817
    }
818
819
        return redirect('/');
820
    }
821
822
    //Delete profile picture
823
    public function delProfilePicture()
824
    {
825
        $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...
826
827
        // Delete the user's current avatar if it exists
828
        while (findAvatar($userId) !== "error.error") {
829
            $avatarName = findAvatar($userId);
830
            unlink(base_path($avatarName));
831
        }
832
833
        return back();
834
    }
835
836
    //Export user links
837
    public function exportLinks(request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

837
    public function exportLinks(/** @scrutinizer ignore-unused */ request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
838
    {
839
        $userId = Auth::id();
840
        $user = User::find($userId);
841
        $links = Link::where('user_id', $userId)->get();
842
        
843
        if (!$user) {
844
            // handle the case where the user is null
845
            return response()->json(['message' => 'User not found'], 404);
846
        }
847
848
        $userData['links'] = $links->toArray();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$userData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $userData = array(); before regardless.
Loading history...
849
850
        $domain = $_SERVER['HTTP_HOST'];
851
        $date = date('Y-m-d_H-i-s');
852
        $fileName = "links-$domain-$date.json";
853
        $headers = [
854
            'Content-Type' => 'application/json',
855
            'Content-Disposition' => 'attachment; filename="'.$fileName.'"',
856
        ];
857
        return response()->json($userData, 200, $headers);
858
859
        return back();
0 ignored issues
show
Unused Code introduced by
return back() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
860
    }
861
862
    //Export all user data
863
    public function exportAll(Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

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

863
    public function exportAll(/** @scrutinizer ignore-unused */ Request $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
864
    {
865
        $userId = Auth::id();
866
        $user = User::find($userId);
867
        $links = Link::where('user_id', $userId)->get();
868
    
869
        if (!$user) {
870
            // handle the case where the user is null
871
            return response()->json(['message' => 'User not found'], 404);
872
        }
873
    
874
        $userData = $user->toArray();
875
        $userData['links'] = $links->toArray();
876
877
        if (file_exists(base_path(findAvatar($userId)))){
878
            $imagePath = base_path(findAvatar($userId));
879
            $imageData = base64_encode(file_get_contents($imagePath));
880
            $userData['image_data'] = $imageData;
881
    
882
            $imageExtension = pathinfo($imagePath, PATHINFO_EXTENSION);
883
            $userData['image_extension'] = $imageExtension;
884
        }
885
    
886
        $domain = $_SERVER['HTTP_HOST'];
887
        $date = date('Y-m-d_H-i-s');
888
        $fileName = "user_data-$domain-$date.json";
889
        $headers = [
890
            'Content-Type' => 'application/json',
891
            'Content-Disposition' => 'attachment; filename="'.$fileName.'"',
892
        ];
893
        return response()->json($userData, 200, $headers);
894
    
895
        return back();
0 ignored issues
show
Unused Code introduced by
return back() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
896
    }    
897
898
    public function importData(Request $request)
899
    {
900
        try {
901
            // Get the JSON data from the uploaded file
902
            if (!$request->hasFile('import') || !$request->file('import')->isValid()) {
903
                throw new \Exception('File not uploaded or is faulty');
904
            }
905
            $file = $request->file('import');
906
            $jsonString = $file->get();
907
            $userData = json_decode($jsonString, true);
908
    
909
            // Update the authenticated user's profile data if defined in the JSON file
910
            $user = auth()->user();
911
            if (isset($userData['name'])) {
912
                $user->name = $userData['name'];
913
            }
914
915
            if (isset($userData['littlelink_description'])) {
916
                $sanitizedText = $userData['littlelink_description'];
917
                $sanitizedText = strip_tags($sanitizedText, '<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
918
                $sanitizedText = preg_replace("/<a([^>]*)>/i", "<a $1 rel=\"noopener noreferrer nofollow\">", $sanitizedText);
919
                $sanitizedText = strip_tags_except_allowed_protocols($sanitizedText);
920
                $user->littlelink_description = $sanitizedText;
921
            }
922
923
            if (isset($userData['image_data'])) {
924
925
                $allowedExtensions = array('jpeg', 'jpg', 'png', 'webp');
926
                $userExtension = strtolower($userData['image_extension']);
927
928
                if (in_array($userExtension, $allowedExtensions)) {
929
                // Decode the image data from Base64
930
                $imageData = base64_decode($userData['image_data']);
931
932
                // Delete the user's current avatar if it exists
933
                while (findAvatar(Auth::id()) !== "error.error") {
934
                    $avatarName = findAvatar(Auth::id());
935
                    unlink(base_path($avatarName));
936
                }
937
                
938
                // Save the image to the correct path with the correct file name and extension
939
                $filename = $user->id . '.' . $userExtension;
940
                file_put_contents(base_path('assets/img/' . $filename), $imageData);
941
                
942
                // Update the user's image field with the correct file name
943
                $user->image = $filename;
944
                }
945
            }
946
947
            $user->save();
948
    
949
            // Delete all links for the authenticated user
950
            Link::where('user_id', $user->id)->delete();
951
    
952
            // Loop through each link in $userData and create a new link for the user
953
            foreach ($userData['links'] as $linkData) {
954
955
                $validatedData = Validator::make($linkData, [
956
                    'link' => 'nullable|exturl',
957
                ]);
958
959
                if ($validatedData->fails()) {
960
                    throw new \Exception('Invalid link');
961
                }
962
963
                $newLink = new Link();
964
    
965
                // Copy over the link data from $linkData to $newLink
966
                $newLink->button_id = $linkData['button_id'];
967
                $newLink->link = $linkData['link'];
968
                
969
                // Sanitize the title
970
                if ($linkData['button_id'] == 93) {
971
                    $sanitizedText = strip_tags($linkData['title'], '<a><p><strong><i><ul><ol><li><blockquote><h2><h3><h4>');
972
                    $sanitizedText = preg_replace("/<a([^>]*)>/i", "<a $1 rel=\"noopener noreferrer nofollow\">", $sanitizedText);
973
                    $sanitizedText = strip_tags_except_allowed_protocols($sanitizedText);
974
                
975
                    $newLink->title = $sanitizedText;
976
                } else {
977
                    $newLink->title = $linkData['title'];
978
                }
979
980
                $newLink->order = $linkData['order'];
981
                $newLink->click_number = 0;
982
                $newLink->up_link = $linkData['up_link'];
983
                $newLink->custom_css = $linkData['custom_css'];
984
                $newLink->custom_icon = $linkData['custom_icon'];
985
                $newLink->type = $linkData['type'];
986
                $newLink->type_params = $linkData['type_params'];
987
    
988
                // Set the user ID to the current user's ID
989
                $newLink->user_id = $user->id;
990
    
991
                // Save the new link to the database
992
                $newLink->save();
993
            }
994
            return redirect('studio/profile')->with('success', __('messages.Profile updated successfully!'));
995
        } catch (\Exception $e) {
996
            return redirect('studio/profile')->with('error', __('messages.An error occurred while updating your profile.'));
997
        }
998
    }
999
    
1000
1001
    // Hanle reports
1002
    function report(Request $request)
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...
1003
    {
1004
        $formData = $request->all();
1005
    
1006
        try {
1007
            Mail::to(env('ADMIN_EMAIL'))->send(new ReportSubmissionMail($formData));
1008
            
1009
            return redirect('report')->with('success', __('messages.report_success'));
1010
        } catch (\Exception $e) {
1011
            return redirect()->back()->with('error', __('messages.report_error'));
1012
        }
1013
    }
1014
1015
    //Edit/save page icons
1016
    public function editIcons(Request $request)
1017
    {
1018
        $inputKeys = array_keys($request->except('_token'));
1019
1020
        $validationRules = [];
1021
1022
        foreach ($inputKeys as $platform) {
1023
            $validationRules[$platform] = 'nullable|exturl|max:255';
1024
        }
1025
1026
        $request->validate($validationRules);
1027
1028
        foreach ($inputKeys as $platform) {
1029
            $link = $request->input($platform);
1030
1031
            if (!empty($link)) {
1032
                $iconId = $this->searchIcon($platform);
1033
1034
                if (!is_null($iconId)) {
1035
                    $this->updateIcon($platform, $link);
1036
                } else {
1037
                    $this->addIcon($platform, $link);
1038
                }
1039
            }
1040
        }
1041
1042
        return redirect('studio/links#icons');
1043
    }
1044
1045
    private function searchIcon($icon)
1046
    {
1047
        return DB::table('links')
1048
            ->where('user_id', Auth::id())
1049
            ->where('title', $icon)
1050
            ->where('button_id', 94)
1051
            ->value('id');
1052
    }
1053
1054
    private function addIcon($icon, $link)
1055
    {
1056
        $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...
1057
        $links = new Link;
1058
        $links->link = $link;
1059
        $links->user_id = $userId;
1060
        $links->title = $icon;
1061
        $links->button_id = '94';
1062
        $links->save();
1063
        $links->order = ($links->id - 1);
1064
        $links->save();
1065
    }
1066
1067
    private function updateIcon($icon, $link)
1068
    {
1069
        Link::where('id', $this->searchIcon($icon))->update([
1070
            'button_id' => 94,
1071
            'link' => $link,
1072
            'title' => $icon
1073
        ]);
1074
    }
1075
}