Passed
Push — master ( 146a05...11c4cf )
by Adam
09:00
created

TopicRepository   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 92
dl 0
loc 184
rs 10
c 0
b 0
f 0
wmc 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A flushRead() 0 3 1
A model() 0 3 1
A interesting() 0 15 1
A countUnread() 0 16 1
A newest() 0 12 1
A adjustReadDate() 0 3 1
A lengthAwarePagination() 0 22 1
A getBuilder() 0 41 1
A findByIds() 0 20 2
1
<?php
2
3
namespace Coyote\Repositories\Eloquent;
4
5
use Carbon\Carbon;
6
use Coyote\Topic;
7
use Coyote\Topic\Track;
8
use Illuminate\Database\Eloquent\Builder;
9
use Illuminate\Database\Eloquent\Relations\BelongsTo;
10
use Illuminate\Database\Query\JoinClause;
11
use Illuminate\Pagination\LengthAwarePaginator;
12
use Coyote\Repositories\Contracts\TopicRepositoryInterface;
13
14
/**
15
 * @method $this withTrashed()
16
 * @method mixed search(\Coyote\Services\Elasticsearch\QueryBuilderInterface $queryBuilder)
17
 */
18
class TopicRepository extends Repository implements TopicRepositoryInterface
19
{
20
    /**
21
     * @return string
22
     */
23
    public function model()
24
    {
25
        return 'Coyote\Topic';
26
    }
27
28
    /**
29
     * @inheritDoc
30
     *
31
     * @uses \Coyote\Topic\user
32
     */
33
    public function lengthAwarePagination($userId, string $guestId, $order = 'topics.last_post_id', $direction = 'DESC', $perPage = 20)
34
    {
35
        $this->applyCriteria();
36
37
        $count = $this->model->count();
38
        $page = LengthAwarePaginator::resolveCurrentPage();
39
40
        $result = $this
41
            ->getBuilder($userId, $guestId)
42
            ->sortable($order, $direction, ['id', 'last', 'replies', 'views', 'score'], ['last' => 'topics.last_post_id'])
43
            ->limit($perPage)
44
            ->offset(max(0, $page - 1) * $perPage)
45
            ->get();
46
47
        $this->resetModel();
48
49
        return new LengthAwarePaginator(
50
            $result,
51
            $count,
52
            $perPage,
53
            $page,
54
            ['path' => LengthAwarePaginator::resolveCurrentPath()]
55
        );
56
    }
57
58
    /**
59
     * @inheritDoc
60
     */
61
    public function findByIds(array $ids, ?int $userId, string $guestId)
62
    {
63
        $this->applyCriteria();
64
65
        $ordering = [];
66
67
        for ($i = 0; $i < count($ids); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
68
            $ordering[] = "($ids[$i],$i)";
69
        }
70
71
        $result = $this
72
            ->getBuilder($userId, $guestId)
73
            ->whereIn('topics.id', $ids)
74
            ->join($this->raw('(VALUES ' . implode(',', $ordering) . ') AS x (id, ordering)'), 'topics.id', '=', 'x.id')
75
            ->orderBy('x.ordering')
76
            ->get();
77
78
        $this->resetModel();
79
80
        return $result;
81
    }
82
83
    private function getBuilder(?int $userId, string $guestId)
84
    {
85
        return $this
86
            ->model
87
            ->select([
88
                'topics.*',
89
                'pa.post_id AS accepted_id',
90
                'p.user_id',
91
                'p.user_name'
92
            ])
93
            ->with([
94
                'user' => function (BelongsTo $builder) {
95
                    return $builder->select(['id', 'name', 'deleted_at', 'is_blocked', 'photo'])->withTrashed();
96
                },
97
                'lastPost' => function ($builder) {
98
                    return $builder->select(['id', 'topic_id', 'user_id', 'created_at', 'user_name'])->with(['user' => function (BelongsTo $builder) {
99
                        return $builder->select(['id', 'name', 'deleted_at', 'is_blocked', 'photo'])->withTrashed();
100
                    }]);
101
                },
102
                'forum' => function ($builder) use ($guestId) {
103
                    return $builder->select(['forums.id', 'name', 'slug'])->withForumMarkTime($guestId);
104
                }
105
            ])
106
            ->withTopicMarkTime($guestId)
107
            ->leftJoin('post_accepts AS pa', 'pa.topic_id', '=', 'topics.id')
108
            ->join('posts AS p', 'p.id', '=', 'topics.first_post_id')
109
            ->with(['tags'])
110
            ->when($userId, function (Builder $builder) use ($userId) {
111
                return $builder->addSelect([
112
                    $this->raw('CASE WHEN ts.created_at IS NULL THEN false ELSE true END AS is_subscribed'),
113
                    $this->raw('CASE WHEN pv.id IS NULL THEN false ELSE true END AS is_voted'),
114
                    $this->raw('CASE WHEN tu.user_id IS NULL THEN false ELSE true END AS is_replied')
115
                ])
116
                ->leftJoin('subscriptions AS ts', function (JoinClause $join) use ($userId) {
117
                    $join->on('ts.resource_id', '=', 'topics.id')->where('ts.resource_type', Topic::class)->where('ts.user_id', $userId);
118
                })
119
                ->leftJoin('post_votes AS pv', function (JoinClause $join) use ($userId) {
120
                    $join->on('pv.post_id', '=', 'first_post_id')->on('pv.user_id', '=', $this->raw($userId));
121
                })
122
                ->leftJoin('topic_users AS tu', function (JoinClause $join) use ($userId) {
123
                    $join->on('tu.topic_id', '=', 'topics.id')->on('tu.user_id', '=', $this->raw($userId));
124
                });
125
            });
126
    }
127
128
    /**
129
     * @inheritdoc
130
     */
131
    public function countUnread($forumId, $markTime, $guestId)
132
    {
133
        return $this
134
            ->model
135
            ->where('topics.forum_id', $forumId)
136
            ->when($markTime, function (Builder $builder) use ($markTime) {
137
                return $builder->where('last_post_created_at', '>', $markTime);
138
            })
139
            ->whereNotIn('topics.id', function ($builder) use ($guestId) {
140
                return $builder
141
                    ->select('topic_track.topic_id')
142
                    ->from('topic_track')
143
                    ->whereColumn('topic_track.topic_id', 'topics.id')
144
                    ->where('topic_track.guest_id', $guestId);
145
            })
146
            ->exists();
147
    }
148
149
    /**
150
     * @inheritDoc
151
     */
152
    public function adjustReadDate(int $topicId, Carbon $carbon): void
153
    {
154
        Track::where('topic_id', $topicId)->where('marked_at', '>', $carbon)->update(['marked_at' => $carbon]);
155
    }
156
157
    /**
158
     * @inheritDoc
159
     */
160
    public function flushRead(int $forumId, string $guestId)
161
    {
162
        return Track::where('forum_id', $forumId)->where('guest_id', $guestId)->delete();
163
    }
164
165
    /**
166
     * @param int $limit
167
     * @return mixed
168
     */
169
    public function newest($limit = 7)
170
    {
171
        $this->applyCriteria();
172
173
        $result = $this
174
            ->model
175
            ->from('topic_recent AS topics')
176
            ->limit($limit)
177
            ->get();
178
179
        $this->resetModel();
180
        return $result;
181
    }
182
183
    /**
184
     * @param int $limit
185
     * @return mixed
186
     */
187
    public function interesting($limit = 7)
188
    {
189
        $this->applyCriteria();
190
191
        $result = $this
192
            ->model
193
            ->from('topic_recent AS topics')
194
            ->where('replies', '>', 0)
195
            ->limit($limit)
196
            ->orderBy('rank', 'DESC')
197
            ->get();
198
199
        $this->resetModel();
200
201
        return $result;
202
    }
203
}
204