Passed
Push — master ( ff4e9f...624a9a )
by Arthur
35:46
created

ScriptService::releaseVersion()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5.4439

Importance

Changes 0
Metric Value
cc 5
eloc 24
nc 8
nop 2
dl 0
loc 33
ccs 17
cts 23
cp 0.7391
crap 5.4439
rs 9.2248
c 0
b 0
f 0
1
<?php
2
3
namespace Modules\Script\Services;
4
5
use Modules\Script\Entities\Script;
6
use Modules\Script\Entities\ScriptConfigProfile;
7
use Modules\Script\Entities\ScriptExclusivity;
8
use Modules\Script\Entities\ScriptRelease;
9
use Modules\Script\Entities\ScriptReview;
10
use Modules\Script\Entities\ScriptReviewReply;
11
use Modules\Script\Events\ScriptWasCreatedEvent;
12
use Modules\Script\Events\ScriptWasUpdatedEvent;
13
use Modules\Script\Events\ScriptWasDeletedEvent;
14
use Modules\Script\Contracts\ScriptServiceContract;
15
use Illuminate\Database\Eloquent\Collection;
16
use Modules\Script\Exceptions\ScriptAlreadyReviewedException;
17
use Modules\Script\Exceptions\ScriptReviewReplyAlreadyExists;
18
use Modules\Script\Exceptions\UserAlreadyHasExclusivityException;
19
use Modules\Script\Exceptions\UserDoesNotHaveExclusivityException;
20
use Modules\Script\Support\Version;
21
22
class ScriptService implements ScriptServiceContract
23
{
24
    /**
25
     * @param $id
26
     * @return Script|null
27
     */
28 10
    public function resolve($id): ?Script
29
    {
30 10
        if ($id instanceof Script) {
31 8
            return $id;
32
        }
33
34 3
        return Script::find($id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Modules\Script\Entities\Script::find($id) could return the type Illuminate\Database\Eloq...go\Abstracts\MongoModel which includes types incompatible with the type-hinted return Modules\Script\Entities\Script|null. Consider adding an additional type-check to rule them out.
Loading history...
35
    }
36
37
    /**
38
     * @param $userId
39
     * @return Script[]
40
     */
41 1
    public function getByUserId($userId): Collection
42
    {
43 1
        return Script::where('user_id', $userId)->get();
0 ignored issues
show
Bug Best Practice introduced by
The expression return Modules\Script\En...er_id', $userId)->get() returns the type Illuminate\Database\Eloquent\Collection which is incompatible with the documented return type Modules\Script\Entities\Script[].
Loading history...
44
    }
45
46
    /**
47
     * @param $id
48
     * @return Script|null
49
     */
50 1
    public function update($id, array $data): Script
51
    {
52 1
        $script = $this->resolve($id);
53 1
        $script->update($data);
54 1
        event(new ScriptWasUpdatedEvent($script));
55
56 1
        return $script;
57
    }
58
59
    /**
60
     * @param $id
61
     * @return Script
62
     */
63 7
    public function create(array $data): Script
64
    {
65 7
        $data[Script::AUTHOR_ID] = get_authenticated_user_id();
66 7
        $script = Script::create($data);
67 7
        event(new ScriptWasCreatedEvent($script));
68 7
        return $script;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $script returns the type Illuminate\Database\Eloq...go\Abstracts\MongoModel which includes types incompatible with the type-hinted return Modules\Script\Entities\Script.
Loading history...
69
    }
70
71
    /**
72
     * @param $id
73
     * @return bool
74
     */
75 1
    public function delete($id): bool
76
    {
77 1
        $script = $this->resolve($id);
78 1
        $deleted = $script->delete();
79 1
        if ($deleted)
80 1
            event(new ScriptWasDeletedEvent($script));
81 1
        return $deleted;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $deleted could return the type null which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
82
    }
83
84 7
    public function releaseVersion($id, array $data): Script
85
    {
86 7
        $script = $this->resolve($id);
87 7
        $releases = $script->releases()->get();
88 7
        if ($releases->isEmpty())
89 7
            $lastVersion = "0.0.0";
90
        else
91 1
            $lastVersion = $releases->last()->version;
92
93 7
        $version = new Version($lastVersion);
94
95 7
        switch ($data['type']) {
96 7
            case 'MAJOR':
97
                $version->incrementMajor();
98
                break;
99 7
            case 'MINOR':
100 7
                $version->incrementMinor();
101 7
                break;
102
            case 'PATCH':
103
                $version->incrementPatch();
104
                break;
105
            default:
106
                throw new \Exception("Invalid release type specified");
107
        }
108
109
        //TODO ADD CONFIG TEMPLATE
110 7
        $script->releases()->create([
111 7
            ScriptRelease::VERSION => $version->__toString(),
112 7
            ScriptRelease::TYPE => $data['type'],
113 7
            ScriptRelease::CHANGELOG => $data['changelog']
114
        ]);
115
116 7
        return $script;
117
    }
118
119 2
    public function publishReview($id, array $data): ScriptReview
120
    {
121 2
        $script = $this->resolve($id);
122
123 2
        if ($script->reviews()->withTrashed()->where(ScriptReview::REVIEWER_ID, get_authenticated_user_id())->get()->isNotEmpty()) {
124 1
            throw new ScriptAlreadyReviewedException();
125
        }
126
        //TODO CHECK IF THE USER IS ACTUALLY SUBSCRIBED TO THE SCRIPT
127
        //TODO PREVENT THE AUTHOR FROM REVIEWING HIS OWN SCRIPT
128
129 2
        $review = $script->reviews()->create([
130 2
            ScriptReview::REVIEWER_ID => get_authenticated_user_id(),
131 2
            ScriptReview::VERSION => $script->releases->last()->version,
0 ignored issues
show
Bug introduced by
The property releases does not seem to exist on Modules\Script\Entities\Script. 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...
132 2
            ScriptReview::MESSAGE => $data['message']
133
        ]);
134
135 2
        return $review;
136
    }
137
138 1
    public function publishReviewReply($id, array $data): ScriptReviewReply
139
    {
140 1
        $script = $this->resolve($id);
141
142 1
        $review = $script->reviews()->withTrashed()->find($data['review_id']);
143
144 1
        if (!isset($review)) {
145
            throw new ScriptAlreadyReviewedException();
146
        }
147
148 1
        if ($review->reply !== null) {
149
            throw new ScriptReviewReplyAlreadyExists();
150
        }
151
152 1
        $reply = $review->reply()->create([
153 1
            ScriptReviewReply::REPLIER_ID => get_authenticated_user_id(),
154 1
            ScriptReviewReply::MESSAGE => $data['message']
155
        ]);
156
157 1
        return $reply;
158
    }
159
160 3
    public function grantUserExclusivity($id, array $data): ScriptExclusivity
161
    {
162 3
        $script = $this->resolve($id);
163 3
        if ($script->exclusivity()->where(ScriptExclusivity::USER_ID, $data['user_id'] ?? null)->first() !== null) {
164
            throw new UserAlreadyHasExclusivityException();
165
        }
166 3
        $exclusivity = $script->exclusivity()->create([
167 3
            ScriptExclusivity::USER_ID => $data['user_id'],
168 3
            ScriptExclusivity::BASE_PRICE => $data['base_price'] ?? 0,
169 3
            ScriptExclusivity::RECURRING_PRICE => $data['recurring_price'] ?? 0
170
        ]);
171
172 3
        return $exclusivity;
173
    }
174
175 1
    public function removeUserExclusivity($id, $userId): bool
176
    {
177 1
        $script = $this->resolve($id);
178 1
        if (($exclusivity = $script->exclusivity()->where(ScriptExclusivity::USER_ID, $userId)->first()) === null) {
179
            throw new UserDoesNotHaveExclusivityException();
180
        }
181
182 1
        return $exclusivity->delete();
183
    }
184
185 1
    public function updateUserExclusivity($id, array $data): ScriptExclusivity
186
    {
187 1
        $script = $this->resolve($id);
188 1
        if (($exclusivity = $script->exclusivity()->where(ScriptExclusivity::USER_ID, $data['user_id'] ?? null)->first()) === null) {
189
            throw new UserDoesNotHaveExclusivityException();
190
        }
191
192 1
        $exclusivity->update([
193 1
            ScriptExclusivity::BASE_PRICE => $data['base_price'] ?? 0,
194 1
            ScriptExclusivity::RECURRING_PRICE => $data['recurring_price'] ?? 0
195
        ]);
196
197 1
        return $exclusivity;
198
    }
199
200
    public function subscribe($id, array $data): ScriptExclusivity
201
    {
202
        // TODO: Implement subscribe() method.
203
    }
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 Modules\Script\Entities\ScriptExclusivity. 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...
204
205
    public function unsubscribe($id, array $data): ScriptExclusivity
206
    {
207
        // TODO: Implement unsubscribe() method.
208
    }
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 Modules\Script\Entities\ScriptExclusivity. 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...
209
210
    public function createConfigProfile($id, array $data): ScriptConfigProfile
211
    {
212
        // TODO: Implement createConfigProfile() method.
213
    }
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 Modules\Script\Entities\ScriptConfigProfile. 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...
214
215
    public function updateConfigProfile($id, array $data): ScriptConfigProfile
216
    {
217
        // TODO: Implement updateConfigProfile() method.
218
    }
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 Modules\Script\Entities\ScriptConfigProfile. 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...
219
220
    public function deleteConfigProfile($id): bool
221
    {
222
        // TODO: Implement deleteConfigProfile() method.
223
    }
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 boolean. 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...
224
225
226
}
227