TenantService::resetRound()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Siak\Tontine\Service;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Relations\Relation;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\DB;
9
use Siak\Tontine\Exception\MessageException;
10
use Siak\Tontine\Model\Round;
11
use Siak\Tontine\Model\Guild;
12
use Siak\Tontine\Model\Session;
13
use Siak\Tontine\Model\User;
14
15
use function is_array;
16
17
class TenantService
18
{
19
    /**
20
     * @var User|null
21
     */
22
    protected ?User $user = null;
23
24
    /**
25
     * @var Guild|null
26
     */
27
    protected ?Guild $guild = null;
28
29
    /**
30
     * @var Round|null
31
     */
32
    protected ?Round $round = null;
33
34
    /**
35
     * @var int
36
     */
37
    protected int $limit = 10;
38
39
    /**
40
     * @param LocaleService $localeService
41
     */
42
    public function __construct(protected LocaleService $localeService)
43
    {}
44
45
    /**
46
     * @param User $user
47
     *
48
     * @return void
49
     */
50
    public function setUser(User $user): void
51
    {
52
        $this->user = $user;
53
    }
54
55
    /**
56
     * @return Builder|Relation
57
     */
58
    private function getGuildQuery(): Builder|Relation
59
    {
60
        return Guild::query()->where(fn(Builder $guild) =>
61
            $guild->where('user_id', $this->user->id)
62
                ->orWhereHas('invites', fn(Builder $invite) =>
63
                    $invite->where('guest_id', $this->user->id)));
64
    }
65
66
    /**
67
     * @return Collection
68
     */
69
    public function getGuilds(): Collection
70
    {
71
        return $this->getGuildQuery()->pluck('name', 'id');
72
    }
73
74
    /**
75
     * @param int $guildId    The guild id
76
     *
77
     * @return Guild|null
78
     */
79
    public function getGuild(int $guildId): ?Guild
80
    {
81
        return $this->getGuildQuery()->find($guildId);
82
    }
83
84
    /**
85
     * @return int
86
     */
87
    public function getLatestGuildId(): int
88
    {
89
        return $this->user?->properties['latest']['guild'] ?? 0;
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist on Siak\Tontine\Model\User. 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...
90
    }
91
92
    /**
93
     * @param Guild $guild
94
     *
95
     * @return void
96
     */
97
    public function setGuild(Guild $guild): void
98
    {
99
        $this->guild = $guild;
100
        // Set the currency for locales.
101
        $this->localeService->setCurrency($guild->currency_code);
102
        // Save as latest guild id if it has changed.
103
        if($this->user === null || $this->getLatestGuildId() === $guild->id)
104
        {
105
            return;
106
        }
107
108
        $properties = $this->user->properties;
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist on Siak\Tontine\Model\User. 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...
109
        $properties['latest']['guild'] = $guild->id;
110
        $this->user->saveProperties($properties);
111
    }
112
113
    /**
114
     * Get a list of rounds for the dropdown select.
115
     *
116
     * @return Collection
117
     */
118
    public function getRounds(): Collection
119
    {
120
        // Only rounds with at least 2 sessions are selectable.
121
        return $this->guild->rounds()
0 ignored issues
show
Bug introduced by
The method rounds() does not exist on null. ( Ignorable by Annotation )

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

121
        return $this->guild->/** @scrutinizer ignore-call */ rounds()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
122
            ->join('sessions', 'sessions.round_id', '=', 'rounds.id')
123
            ->select('rounds.title', 'rounds.id', DB::raw('count(sessions.id)'))
124
            ->groupBy('rounds.title', 'rounds.id')
125
            ->havingRaw('count(sessions.id) > ?', [1])
126
            ->pluck('title', 'id');
127
    }
128
129
    /**
130
     * @param int $roundId    The round id
131
     *
132
     * @return Round|null
133
     */
134
    public function getRound(int $roundId): ?Round
135
    {
136
        return $this->guild->rounds()->find($roundId);
137
    }
138
139
    /**
140
     * @return Round|null
141
     */
142
    public function getFirstRound(): ?Round
143
    {
144
        return $this->guild->rounds()->first();
145
    }
146
147
    /**
148
     * @return int
149
     */
150
    public function getLatestRoundId(): int
151
    {
152
        return $this->user?->properties['latest']['round'][$this->guild->id] ?? 0;
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist on Siak\Tontine\Model\User. 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...
153
    }
154
155
    /**
156
     * @param Round $round
157
     *
158
     * @return void
159
     */
160
    public function setRound(Round $round): void
161
    {
162
        $this->round = $round;
163
        // Save as latest round id if it has changed.
164
        if($this->user === null || $this->getLatestRoundId() === $round->id)
165
        {
166
            return;
167
        }
168
169
        $properties = $this->user->properties;
0 ignored issues
show
Bug introduced by
The property properties does not seem to exist on Siak\Tontine\Model\User. 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...
170
        if(!is_array($properties['latest']['round'] ?? []))
171
        {
172
            // Discard any previous value which is not an array.
173
            $properties['latest']['round'] = [];
174
        }
175
        $properties['latest']['round'][$this->guild->id] = $round->id;
176
        $this->user->saveProperties($properties);
177
    }
178
179
    /**
180
     * @return void
181
     */
182
    public function resetRound(): void
183
    {
184
        $this->round = null;
185
    }
186
187
    /**
188
     * @return User|null
189
     */
190
    public function user(): ?User
191
    {
192
        return $this->user;
193
    }
194
195
    /**
196
     * @return Guild|null
197
     */
198
    public function guild(): ?Guild
199
    {
200
        return $this->guild;
201
    }
202
203
    /**
204
     * @return Round|null
205
     */
206
    public function round(): ?Round
207
    {
208
        return $this->round;
209
    }
210
211
    /**
212
     * @return int
213
     */
214
    public function getLimit(): int
215
    {
216
        return $this->limit;
217
    }
218
219
    /**
220
     * @return bool
221
     */
222
    private function userIsGuest(): bool
223
    {
224
        return $this->guild !== null && $this->guild->isGuest;
225
    }
226
227
    /**
228
     * @return array
229
     */
230
    private function getHostAccess(): array
231
    {
232
        if(!$this->guild || !$this->user)
233
        {
234
            return [];
235
        }
236
        $userInvite = $this->guild->invites()
237
            ->where('guest_id', $this->user->id)
238
            ->first();
239
        if(!$userInvite)
240
        {
241
            return [];
242
        }
243
244
        return $userInvite->options->access;
245
    }
246
247
    /**
248
     * Check guest user access to a menu entry in a section
249
     *
250
     * @param string $section
251
     * @param string $entry
252
     * @param bool $return
253
     *
254
     * @return bool
255
     * @throws MessageException
256
     */
257
    public function checkHostAccess(string $section, string $entry, bool $return = false): bool
258
    {
259
        if(!$this->userIsGuest())
260
        {
261
            return true;
262
        }
263
264
        $guestAccess = $this->getHostAccess();
265
        if(!($guestAccess[$section][$entry] ?? false))
266
        {
267
            if($return)
268
            {
269
                return false;
270
            }
271
            throw new MessageException(trans('tontine.invite.errors.access_denied'));
272
        }
273
        return true;
274
    }
275
276
    /**
277
     * @param int $roundId
278
     * 
279
     * @return Round|null
280
     */
281
    public function getRoundById(int $roundId): Round|null
282
    {
283
        return $this->guild->rounds()->find($roundId);
284
    }
285
286
    /**
287
     * @param int $sessionId
288
     *
289
     * @return Session|null
290
     */
291
    public function getSessionById(int $sessionId): Session|null
292
    {
293
        $session = $this->guild->sessions()->with('round')->find($sessionId);
294
        if($session !== null)
295
        {
296
            $this->setRound($session->round);
297
        }
298
        return $session;
299
    }
300
}
301