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

HomeController   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 282
rs 10
c 0
b 0
f 0
wmc 28

16 Methods

Rating   Name   Duplication   Size   Complexity  
A preview() 0 6 1
A index() 0 5 1
A interesting() 0 5 1
A tag() 0 13 1
A loadAndRender() 0 3 1
A all() 0 5 1
A mark() 0 6 2
A load() 0 21 2
A mine() 0 3 1
A view() 0 16 4
A render() 0 11 3
A unanswered() 0 5 1
B user() 0 26 3
B __construct() 0 34 4
A subscribes() 0 5 1
A categories() 0 15 1
1
<?php
2
3
namespace Coyote\Http\Controllers\Forum;
4
5
use Coyote\Http\Factories\FlagFactory;
6
use Coyote\Http\Factories\GateFactory;
7
use Coyote\Repositories\Contracts\ForumRepositoryInterface as ForumRepository;
8
use Coyote\Repositories\Contracts\TopicRepositoryInterface as TopicRepository;
9
use Coyote\Repositories\Contracts\PostRepositoryInterface as PostRepository;
10
use Coyote\Repositories\Contracts\UserRepositoryInterface;
11
use Coyote\Repositories\Criteria\Topic\OnlyMine;
12
use Coyote\Repositories\Criteria\Topic\SkipForum;
13
use Coyote\Repositories\Criteria\Topic\SkipLockedCategories;
14
use Coyote\Repositories\Criteria\Topic\Subscribes;
15
use Coyote\Repositories\Criteria\Topic\Unanswered;
16
use Coyote\Repositories\Criteria\Topic\OnlyThoseWithAccess;
17
use Coyote\Repositories\Criteria\Topic\WithTags;
18
use Coyote\Services\Forum\TreeBuilder;
19
use Coyote\Services\Forum\Personalizer;
20
use Illuminate\Http\Request;
21
use Lavary\Menu\Item;
22
use Lavary\Menu\Menu;
23
use Lavary\Menu\Builder;
24
25
class HomeController extends BaseController
26
{
27
    use GateFactory, FlagFactory;
28
29
    /**
30
     * @var Builder
31
     */
32
    private $tabs;
33
34
    /**
35
     * @var Personalizer
36
     */
37
    private $personalizer;
38
39
    /**
40
     * @param ForumRepository $forum
41
     * @param TopicRepository $topic
42
     * @param PostRepository $post
43
     * @param Personalizer $personalizer
44
     */
45
    public function __construct(
46
        ForumRepository $forum,
47
        TopicRepository $topic,
48
        PostRepository $post,
49
        Personalizer $personalizer
50
    ) {
51
        parent::__construct($forum, $topic, $post);
52
53
        $this->personalizer = $personalizer;
54
55
        $this->tabs = app(Menu::class)->make('_forum', function (Builder $menu) {
0 ignored issues
show
Documentation Bug introduced by
It seems like app(Lavary\Menu\Menu::cl...ion(...) { /* ... */ }) of type Lavary\Menu\Menu is incompatible with the declared type Lavary\Menu\Builder of property $tabs.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
56
            foreach (config('laravel-menu._forum') as $title => $row) {
57
                $data = array_pull($row, 'data');
58
                $menu->add($title, $row)->data($data);
59
            }
60
        });
61
62
        $this->middleware(function (Request $request, $next) {
63
            $this->tabs->filter(function (Item $item) {
64
                if ($item->data('role') === true) {
0 ignored issues
show
introduced by
The condition $item->data('role') === true can never be true.
Loading history...
65
                    return $this->userId !== null;
66
                }
67
68
                return true;
69
            });
70
71
            // currently selected tab
72
            list(, $suffix) = explode('.', $request->route()->getName());
73
74
            if (in_array($suffix, ['categories', 'all', 'unanswered', 'subscribes', 'mine', 'interesting'])) {
75
                $this->setSetting('forum.tab', $suffix);
76
            }
77
78
            return $next($request);
79
        });
80
    }
81
82
    /**
83
     * @param string $view
84
     * @param array $data
85
     * @return \Illuminate\View\View
86
     */
87
    protected function view($view = null, $data = [])
88
    {
89
        list(, $suffix) = explode('.', $this->request->route()->getName());
90
91
        $currentTab = $suffix == 'home' ? $this->getSetting('forum.tab', 'categories') : $suffix;
92
        $title = null;
93
94
        foreach ($this->tabs->all() as $tab) {
95
            if ("forum.$currentTab" == $tab->link->path['route']) {
96
                $tab->activate();
97
98
                $title = $tab->title;
99
            }
100
        }
101
102
        return parent::view($view, $data)->with(['tabs' => $this->tabs, 'title' => $title]);
103
    }
104
105
    /**
106
     * @return \Illuminate\View\View
107
     */
108
    public function index()
109
    {
110
        $tab = $this->getSetting('forum.tab', 'categories');
111
112
        return $this->{$tab}();
113
    }
114
115
    /**
116
     * @param Request $request
117
     * @return \Symfony\Component\HttpFoundation\Response
118
     */
119
    public function preview(Request $request)
120
    {
121
        $parser = app('parser.post');
122
        $parser->cache->setEnable(false);
123
124
        return response($parser->parse($request->get('text')));
0 ignored issues
show
Bug Best Practice introduced by
The expression return response($parser-...$request->get('text'))) also could return the type Illuminate\Contracts\Routing\ResponseFactory which is incompatible with the documented return type Symfony\Component\HttpFoundation\Response.
Loading history...
125
    }
126
127
    /**
128
     * @return \Illuminate\View\View
129
     */
130
    public function categories()
131
    {
132
        $this->pushForumCriteria();
133
        // execute query: get all categories that user can has access
134
        $sections = $this->forum->categories($this->guestId);
135
        // establish forum's marked date
136
        $sections = $this->personalizer->markUnreadCategories($sections);
137
138
        $treeBuilder = new TreeBuilder();
139
        $sections = $treeBuilder->sections($sections);
140
141
        // get categories collapse
142
        $collapse = $this->collapse();
143
144
        return $this->view('forum.home')->with(compact('sections', 'collapse'));
145
    }
146
147
    /**
148
     * @return \Illuminate\View\View
149
     */
150
    public function all()
151
    {
152
        $this->topic->pushCriteria(new SkipLockedCategories());
153
154
        return $this->loadAndRender();
155
    }
156
157
    /**
158
     * @return \Illuminate\View\View
159
     */
160
    public function unanswered()
161
    {
162
        $this->topic->pushCriteria(new Unanswered());
163
164
        return $this->loadAndRender();
165
    }
166
167
    /**
168
     * @return \Illuminate\View\View
169
     */
170
    public function mine()
171
    {
172
        return $this->user($this->userId);
173
    }
174
175
    /**
176
     * @param int $userId
177
     * @return \Illuminate\View\View
178
     */
179
    public function user($userId)
180
    {
181
        $this->topic->pushCriteria(new OnlyMine($userId));
182
        $topics = $this->load();
183
184
        if ($topics->total() > 0) {
185
            $topics->load(['posts' => function ($query) use ($userId) {
186
                $query->where('user_id', $userId);
187
            }]);
188
        }
189
190
        $user = app(UserRepositoryInterface::class)->find($userId);
191
        abort_if(is_null($user), 404);
192
193
        if ($this->request->route()->getName() == 'forum.user') {
194
            $this
195
                ->tabs
196
                ->add('Posty: ' . $user->name, [
197
                    'route' => [
198
                        'forum.user', $userId
199
                    ]
200
                ])
201
                ->activate();
202
        }
203
204
        return $this->render($topics)->with('user_id', $userId);
205
    }
206
207
    /**
208
     * @return \Illuminate\View\View
209
     */
210
    public function subscribes()
211
    {
212
        $this->topic->pushCriteria(new Subscribes($this->userId));
213
214
        return $this->loadAndRender();
215
    }
216
217
    /**
218
     * @param string $name
219
     * @return \Illuminate\View\View
220
     */
221
    public function tag($name)
222
    {
223
        $this
224
            ->tabs
225
            ->add('Wątki z: ' . $this->request->route('tag'), [
0 ignored issues
show
Bug introduced by
Are you sure $this->request->route('tag') of type object|string|Illuminate\Routing\Route can be used in concatenation? ( Ignorable by Annotation )

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

225
            ->add('Wątki z: ' . /** @scrutinizer ignore-type */ $this->request->route('tag'), [
Loading history...
226
                'route' => [
227
                    'forum.tag', urlencode($this->request->route('tag'))
0 ignored issues
show
Bug introduced by
It seems like $this->request->route('tag') can also be of type object and Illuminate\Routing\Route; however, parameter $str of urlencode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

227
                    'forum.tag', urlencode(/** @scrutinizer ignore-type */ $this->request->route('tag'))
Loading history...
228
                ]
229
            ])
230
            ->activate();
231
232
        $this->topic->pushCriteria(new WithTags($name));
233
        return $this->loadAndRender();
234
    }
235
236
    /**
237
     * @return \Illuminate\View\View
238
     */
239
    public function interesting()
240
    {
241
        $this->topic->pushCriteria(new WithTags(json_decode($this->getSetting('forum.tags', '[]'))));
242
243
        return $this->loadAndRender();
244
    }
245
246
    /**
247
     * Mark ALL categories as READ
248
     */
249
    public function mark()
250
    {
251
        $forums = $this->forum->all(['id']);
252
253
        foreach ($forums as $forum) {
254
            $this->forum->markAsRead($forum->id, $this->guestId);
255
        }
256
    }
257
258
    /**
259
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
260
     */
261
    private function load()
262
    {
263
        $this->topic->pushCriteria(new OnlyThoseWithAccess($this->auth));
264
265
        // if someone wants to find all user's topics, we can't hide those from our hidden categories.
266
        if (strpos($this->request->route()->getActionName(), '@user') === false) {
267
            $this->topic->pushCriteria(new SkipForum($this->forum->order->findHiddenIds($this->userId)));
0 ignored issues
show
Bug introduced by
Accessing order on the interface Coyote\Repositories\Cont...orumRepositoryInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
268
        }
269
270
        $paginator = $this
271
            ->topic
272
            ->paginate(
273
                $this->userId,
274
                $this->guestId,
275
                'topics.last_post_id',
276
                'DESC',
277
                $this->topicsPerPage($this->request)
278
            )
279
            ->appends($this->request->except('page'));
280
281
        return $this->personalizer->markUnreadTopics($paginator);
282
    }
283
284
    /**
285
     * @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $topics
286
     * @return \Illuminate\View\View
287
     */
288
    private function render($topics)
289
    {
290
        // we need to get an information about flagged topics. that's how moderators can notice
291
        // that's something's wrong with posts.
292
        if ($topics->total() && $this->getGateFactory()->allows('forum-delete')) {
293
            $flags = $this->getFlagFactory()->takeForTopics($topics->groupBy('id')->keys()->toArray());
294
        }
295
296
        $postsPerPage = $this->postsPerPage($this->request);
297
298
        return $this->view('forum.topics')->with(compact('topics', 'flags', 'postsPerPage'));
299
    }
300
301
    /**
302
     * @return \Illuminate\View\View
303
     */
304
    private function loadAndRender()
305
    {
306
        return $this->render($this->load());
307
    }
308
}
309