Passed
Branch master (249862)
by Adam
07:51
created

ForumRepository::categoriesOrder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 15
nc 1
nop 1
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
1
<?php
2
3
namespace Coyote\Repositories\Eloquent;
4
5
use Coyote\Repositories\Contracts\Forum\OrderRepositoryInterface;
6
use Coyote\Repositories\Contracts\ForumRepositoryInterface;
7
use Coyote\Forum\Track as Forum_Track;
8
use Coyote\Topic\Track as Topic_Track;
9
use Coyote\Topic;
10
use Coyote\Forum;
11
use Illuminate\Container\Container as App;
12
use Illuminate\Database\Eloquent\Builder;
13
use Illuminate\Database\Query\JoinClause;
14
15
class ForumRepository extends Repository implements ForumRepositoryInterface
16
{
17
    /**
18
     * @var OrderRepositoryInterface
19
     */
20
    public $order;
21
22
    /**
23
     * @inheritdoc
24
     */
25
    public function __construct(App $app)
26
    {
27
        parent::__construct($app);
28
29
        $this->order = $this->app[OrderRepositoryInterface::class];
30
    }
31
32
    /**
33
     * @return string
34
     */
35
    public function model()
36
    {
37
        return Forum::class;
38
    }
39
40
    /**
41
     * @inheritdoc
42
     */
43
    public function categories($guestId, $parentId = null)
44
    {
45
        $this->applyCriteria();
46
47
        $result = $this
48
            ->model
49
            ->select([
50
                'forums.*',
51
                'subject',
52
                'topics.id AS topic_id',
53
                'topics.slug AS topic_slug',
54
                'posts.user_id',
55
                'posts.created_at',
56
                'posts.user_name AS anonymous_name',
57
                'users.name AS user_name',
58
                'users.photo',
59
                'is_active',
60
                'is_confirm'
61
            ])
62
            ->leftJoin('posts', 'posts.id', '=', 'forums.last_post_id')
63
            ->leftJoin('users', 'users.id', '=', 'posts.user_id')
64
            ->leftJoin('topics', 'topics.id', '=', 'posts.topic_id')
65
            ->trackForum($guestId)
66
            ->trackTopic($guestId)
67
            ->when($parentId, function (Builder $builder) use ($parentId) {
68
                return $builder->where('parent_id', $parentId);
69
            })
70
            ->get();
71
72
        $this->resetModel();
73
74
        return $result;
75
    }
76
77
    /**
78
     * @param int $userId
79
     * @return mixed
80
     */
81
    public function categoriesOrder($userId)
82
    {
83
        $this->applyCriteria();
84
85
        $sql = $this
86
            ->model
87
            ->select([
88
                'forums.*',
89
                'forum_orders.is_hidden',
90
                $this->raw('CASE WHEN forum_orders.section IS NOT NULL THEN forum_orders.section ELSE forums.section END')
91
            ])
92
            ->leftJoin('forum_orders', function (JoinClause $join) use ($userId) {
93
                $join->on('forum_orders.forum_id', '=', 'forums.id')
94
                        ->on('forum_orders.user_id', '=', $this->raw($userId));
95
            })
96
            ->whereNull('parent_id')
97
            ->orderByRaw('(CASE WHEN forum_orders.order IS NOT NULL THEN forum_orders.order ELSE forums.order END)');
98
99
        $parents = $sql->get();
100
101
        $this->resetModel();
102
103
        return $parents;
104
    }
105
106
    /**
107
     * Get restricted access forums.
108
     *
109
     * @return int[]
110
     */
111
    public function getRestricted()
112
    {
113
        return (new Forum\Access)->groupBy('forum_id')->get(['forum_id'])->pluck('forum_id')->toArray();
114
    }
115
116
    /**
117
     * @inheritdoc
118
     */
119
    public function list()
120
    {
121
        return $this->applyCriteria(function () {
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->applyCrite...ion(...) { /* ... */ }) also could return the type Coyote\Repositories\Eloquent\ForumRepository which is incompatible with the return type mandated by Coyote\Repositories\Cont...sitoryInterface::list() of Coyote\Forum[].
Loading history...
122
            return $this->model->select('forums.id', 'name', 'slug', 'parent_id')->orderBy('forums.order')->get();
123
        });
124
    }
125
126
    /**
127
     * @return array
128
     */
129
    public function getTagsCloud()
130
    {
131
        return $this
132
            ->tags()
133
            ->orderBy($this->raw('COUNT(*)'), 'DESC')
134
            ->limit(10)
135
            ->get()
136
            ->pluck('count', 'name')
137
            ->toArray();
138
    }
139
140
    /**
141
     * @param array $tags
142
     * @return array
143
     */
144
    public function getTagsWeight(array $tags)
145
    {
146
        return $this
147
            ->tags()
148
            ->whereIn('tags.name', $tags)
149
            ->orderBy($this->raw('COUNT(*)'), 'DESC')
150
            ->get()
151
            ->pluck('count', 'name')
152
            ->toArray();
153
    }
154
155
    /**
156
     * @param int $id
157
     */
158
    public function up($id)
159
    {
160
        $this->changeForumOrder($id, '<');
161
    }
162
163
    /**
164
     * @param int $id
165
     */
166
    public function down($id)
167
    {
168
        $this->changeForumOrder($id, '>');
169
    }
170
171
    /**
172
     * @param int $id
173
     * @param string $operator
174
     */
175
    private function changeForumOrder($id, $operator)
176
    {
177
        /** @var \Coyote\Forum $forum */
178
        /** @var \Coyote\Forum $other */
179
        $forum = $this->model->findOrFail($id, ['id', 'order', 'parent_id']);
180
181
        $other = $this
182
            ->model
183
            ->select(['id', 'order', 'parent_id'])
184
            ->where('parent_id', $forum->parent_id)
185
            ->where('order', $operator, $forum->order)
186
            ->orderBy('order', $operator == '<' ? 'DESC' : 'ASC')
187
            ->first();
188
189
        if ($other) {
190
            $forum->order = $other->order;
191
            $other->order = $forum->getOriginal('order');
192
193
            $forum->save();
194
            $other->save();
195
        }
196
    }
197
198
    /**
199
     * @return mixed
200
     */
201
    private function tags()
202
    {
203
        return $this
204
            ->app
205
            ->make(Topic\Tag::class)
206
            ->select(['name', $this->raw('COUNT(*) AS count')])
207
            ->join('tags', 'tags.id', '=', 'tag_id')
208
            ->join('topics', 'topics.id', '=', 'topic_id')
209
                ->whereNull('topics.deleted_at')
210
                ->whereNull('tags.deleted_at')
211
            ->groupBy('name');
0 ignored issues
show
Bug introduced by
'name' of type string is incompatible with the type array expected by parameter $groups of Illuminate\Database\Query\Builder::groupBy(). ( Ignorable by Annotation )

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

211
            ->groupBy(/** @scrutinizer ignore-type */ 'name');
Loading history...
212
    }
213
214
    /**
215
     * Mark forum as read
216
     *
217
     * @param $forumId
218
     * @param $guestId
219
     */
220
    public function markAsRead($forumId, $guestId)
221
    {
222
        // builds data to update
223
        $attributes = ['forum_id' => $forumId, 'guest_id' => $guestId];
224
        // execute a query...
225
        Forum_Track::updateOrCreate($attributes, $attributes + ['marked_at' => $this->raw('NOW()'), 'forum_id' => $forumId]);
226
        $track = new Topic_Track();
227
228
        foreach ($attributes as $key => $value) {
229
            $track = $track->where($key, $value);
230
        }
231
232
        $track->delete();
233
    }
234
}
235