UrlService::validateUrl()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 5
Bugs 1 Features 1
Metric Value
cc 2
eloc 7
c 5
b 1
f 1
nc 2
nop 1
dl 0
loc 11
ccs 8
cts 8
cp 1
crap 2
rs 10
1
<?php
2
3
namespace Devpri\Tinre\Services;
4
5
use Devpri\Tinre\Models\Url;
6
use Exception;
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Support\Facades\DB;
9
use Illuminate\Support\Facades\Validator;
10
use Illuminate\Support\Str;
11
use Illuminate\Validation\ValidationException;
12
13
class UrlService
14
{
15 14
    public function index($data, $user)
16
    {
17 14
        $search = $data['search'] ?? null;
18 14
        $userId = $data['user_id'] ?? null;
19 14
        $startDate = $data['start_date'] ?? null;
20 14
        $endDate = $data['end_date'] ?? null;
21 14
        $limit = $data['limit'] ?? 25;
22 14
        $active = $data['active'] ?? null;
23 14
        $sortBy = $data['sort_by'] ?? 'created_at';
24 14
        $sortDirection = $data['sort_direction'] ?? 'desc';
25
26 14
        $query = Url::query();
27
28 14
        $query->when($user->cant('viewAny', Url::class), function ($query) use ($user) {
29 11
            return $query->where('user_id', $user->id);
30 14
        });
31
32 14
        $query->when($userId, function ($query) use ($userId) {
33 2
            return $query->where('user_id', $userId);
34 14
        });
35
36 14
        $query->when($search, function ($query) use ($search) {
37 1
            return $query->where(function (Builder $query) use ($search) {
38 1
                return $query->where('path', 'LIKE', "%{$search}%")
39 1
                    ->orWhere('long_url', 'LIKE', "%{$search}%");
40 1
            });
41 14
        });
42
43 14
        $query->when($startDate && $endDate, function ($query) use ($startDate, $endDate) {
44 1
            return $query->whereBetween('created_at', [$startDate, $endDate]);
45 14
        });
46
47 14
        $query->when(isset($active), function ($query) use ($active) {
48 2
            return $query->where('active', $active);
49 14
        });
50
51 14
        return $query->orderBy($sortBy, $sortDirection)->with('user')->paginate($limit);
52
    }
53
54 11
    public function create($longUrl, $path = null, $user = null): Url
55
    {
56 11
        $this->validateUrl($longUrl);
57
58 9
        $url = new Url();
59 9
        $url->long_url = $longUrl;
60 9
        $url->user_id = $user ? $user->id : null;
61
62 9
        $path = $user || config('tinre.guest_form_custom_path') ? $path : null;
63
64 9
        if ($path) {
65 5
            $this->validatePath($path);
66
67 3
            $url->path = $path;
68 3
            $url->save();
69
70 3
            return $url;
71
        }
72
73 4
        $maxGenerationAttempts = 5;
74
75 4
        while ($maxGenerationAttempts-- > 0) {
76
            try {
77 4
                $url->path = strtolower(Str::random(config('tinre.default_path_length')));
78
79 4
                $this->validatePath($url->path);
80
81 4
                $url->save();
82
83 4
                return $url;
84
            } catch (Exception $e) {
85
                if ($maxGenerationAttempts === 0) {
86
                    throw $e;
87
                }
88
            }
89
        }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Devpri\Tinre\Models\Url. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
90
    }
91
92 9
    public function update($id, $active, $longUrl, $path, $user): Url
93
    {
94 9
        $this->validateUrl($longUrl);
95
96 7
        $url = Url::where('id', $id)->firstOrFail();
97
98 7
        if ($url->path != $path) {
99 7
            $this->validatePath($path);
100
        }
101
102 6
        if ($user->cant('update', $url)) {
103 1
            abort(401);
104
        }
105
106 5
        $url->active = $active;
107 5
        $url->long_url = $longUrl;
108 5
        $url->path = $path;
109 5
        $url->save();
110
111 5
        return $url;
112
    }
113
114 16
    protected function validatePath($path): void
115
    {
116 16
        Validator::make([
117 16
            'path' => $path,
118
        ], [
119 16
            'path' => ['required', 'alpha_dash', 'min:'.config('tinre.min_path_length'), 'max:'.config('tinre.max_path_length')],
120 16
        ])->validate();
121
122 14
        $path = strtolower($path);
123
124 14
        $url = DB::table('urls')->whereRaw('lower(path) like (?)', ["%{$path}%"])->count();
125
126 14
        if ($url) {
127 1
            throw ValidationException::withMessages([
128 1
                'path' => [__('The path has already been taken.')],
129
            ]);
130
        }
131
132 14
        if (in_array($path, config('tinre.restricted_paths'))) {
133 1
            throw ValidationException::withMessages([
134 1
                'path' => [__('Restricted path.')],
135
            ]);
136
        }
137 13
    }
138
139 20
    protected function validateUrl($url): void
140
    {
141 20
        Validator::make([
142 20
            'long_url' => $url,
143
        ], [
144 20
            'long_url' => ['required', 'url', 'active_url'],
145 20
        ])->validate();
146
147 17
        if (in_array(parse_url($url, PHP_URL_HOST), config('tinre.restricted_domains'))) {
148 1
            throw ValidationException::withMessages([
149 1
                'long_url' => [__('Restricted domain.')],
150
            ]);
151
        }
152 16
    }
153
}
154