Completed
Push — master ( 5c55d7...79e99a )
by Fèvre
28s queued 15s
created

Conversation::select()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 12
rs 10
1
<?php
2
3
namespace Xetaravel\Http\Livewire\Discuss;
4
5
use Illuminate\Contracts\Database\Query\Builder;
6
use Illuminate\Contracts\View\View;
7
use Illuminate\Pagination\LengthAwarePaginator;
8
use Illuminate\Support\Collection;
9
use Livewire\Component;
10
use Livewire\WithPagination;
11
use Xetaravel\Http\Livewire\Traits\WithSorting;
12
use Xetaravel\Models\DiscussCategory;
13
use Xetaravel\Models\DiscussConversation;
14
15
class Conversation extends Component
16
{
17
    use WithPagination;
18
    use WithSorting;
19
20
    /**
21
     * The string to search.
22
     *
23
     * @var string
24
     */
25
    public string $search = '';
26
27
    /**
28
     * Categories used for sorting.
29
     *
30
     * @var Collection
31
     */
32
    public $categories;
33
34
    /**
35
     * The category selected in the select menu.
36
     *
37
     * 0 = all categories
38
     *
39
     * @var int
40
     */
41
    public $category = 0;
42
43
    /**
44
     * Tell if the categories select menu is open or not.
45
     *
46
     * @var bool
47
     */
48
    public $open = false;
49
50
    /**
51
     * The number of conversation limited per page.
52
     *
53
     * @var null|int
54
     */
55
    public $limit = null;
56
57
    /**
58
     * The default number used to limit conversations per page.
59
     *
60
     * @var int[]
61
     */
62
    public $perPage = [
63
        10,
64
        25,
65
        50
66
    ];
67
68
    /**
69
     * Used to update in URL the query string.
70
     *
71
     * @var string[]
72
     */
73
    protected $queryString = [
74
        'sortField' => ['as' => 'f'],
75
        'sortDirection' => ['as' => 'd'],
76
        'search' => ['except' => '', 'as' => 's'],
77
        'category' => ['except' => 'all', 'as' => 'c'],
78
        'limit' => ['as' => 'l']
79
    ];
80
81
    /**
82
     * The theme used for pagination.
83
     *
84
     * @var string
85
     */
86
    protected string $paginationTheme = 'tailwind';
87
88
    /**
89
     * The Livewire Component constructor.
90
     *
91
     * @return void
92
     */
93
    public function mount(): void
94
    {
95
        // Create the categories list for the select and push the `All Categories` into it at the first position.
96
        $categories = collect();
97
        $categories->push([
0 ignored issues
show
Bug introduced by
array('id' => 0, 'icon' ...lor' => 'currentColor') of type array<string,integer|string> is incompatible with the type Illuminate\Support\TValue expected by parameter $values of Illuminate\Support\Collection::push(). ( Ignorable by Annotation )

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

97
        $categories->push(/** @scrutinizer ignore-type */ [
Loading history...
98
            'id' => 0,
99
            'icon' => 'fa-solid fa-list',
100
            'title' => 'All Categories',
101
            'color' => 'currentColor'
102
        ]);
103
104
        // Get and push all the discuss categories.
105
        $categoriesAll = DiscussCategory::orderBy('id', 'asc')->get();
106
        $categoriesAll->each(function ($item) use ($categories) {
107
            $categories->push([
0 ignored issues
show
Bug introduced by
array('id' => $item->id,...color' => $item->color) of type array is incompatible with the type Illuminate\Support\TValue expected by parameter $values of Illuminate\Support\Collection::push(). ( Ignorable by Annotation )

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

107
            $categories->push(/** @scrutinizer ignore-type */ [
Loading history...
108
                'id' => $item->id,
109
                'icon' => $item->icon,
110
                'title' => $item->title,
111
                'color' => $item->color
112
            ]);
113
        });
114
        // Reorder the collection by `id` key and convert to array.
115
        $this->categories = $categories->keyBy('id');
116
117
        // Add the default perPage setting to the array.
118
        $this->perPage[] = config('xetaravel.pagination.discuss.conversation_per_page');
119
        // Re-order the array by `asc`.
120
        sort($this->perPage);
121
122
        // Set the limit to the default config if the limit is not in the array.
123
        if (!in_array($this->limit, $this->perPage)) {
124
            $this->limit = config('xetaravel.pagination.discuss.conversation_per_page');
125
        }
126
127
        // Set the allowed fields.
128
        $this->allowedFields += ['created_at', 'is_solved', 'is_locked', 'post_count'];
129
130
        // Check if the field is allowed before setting it.
131
        if (!in_array($this->sortField, $this->allowedFields)) {
132
            $this->sortField = 'created_at';
133
        }
134
135
        // Check if the category exist, else set the all categories.
136
        if (!$this->categories->has($this->category)) {
137
            $this->category = 0;
138
        }
139
    }
140
141
    /**
142
     * Function to render the component.
143
     *
144
     * @return View
145
     */
146
    public function render()
147
    {
148
        return view('livewire.discuss.conversation', [
149
            'conversations' => $this->conversations
0 ignored issues
show
Bug Best Practice introduced by
The property conversations does not exist on Xetaravel\Http\Livewire\Discuss\Conversation. Since you implemented __get, consider adding a @property annotation.
Loading history...
150
        ]);
151
    }
152
153
    /**
154
     * Create and return the query for the conversations.
155
     *
156
     * @return Builder
157
     */
158
    public function getConversationsQueryProperty(): Builder
159
    {
160
        $search = $this->search;
161
        $query = DiscussConversation::query()
162
            ->with(['User', 'Category', 'FirstPost', 'LastPost', 'Users' => function ($query) {
163
                return $query->with('User')->limit(4);
164
            }])
165
            ->where(function ($query) use ($search) {
166
                $query->where('title', 'LIKE', '%' . $search . '%')
167
                    ->orWhereHas('posts', function ($query) use ($search) {
168
                        return $query->where('content', 'like', '%' . $search . '%');
169
                    });
170
            })
171
            ->orderBy('is_pinned', 'desc');
172
173
        // If the `selected` == 0, we display all categories so no condition applied.
174
        if ($this->category != 0) {
175
            $query = $query->where('category_id', $this->category);
176
        }
177
178
        return $this->applySorting($query);
179
    }
180
181
    /**
182
     * Build the query and paginate it.
183
     *
184
     * @return LengthAwarePaginator
185
     */
186
    public function getConversationsProperty(): LengthAwarePaginator
187
    {
188
        return $this->conversationsQuery->paginate($this->limit);
0 ignored issues
show
Bug Best Practice introduced by
The property conversationsQuery does not exist on Xetaravel\Http\Livewire\Discuss\Conversation. Since you implemented __get, consider adding a @property annotation.
Loading history...
189
    }
190
191
    /**
192
     * Toggle open/close the categories select menu.
193
     *
194
     * @return void
195
     */
196
    public function toggle(): void
197
    {
198
        $this->open = !$this->open;
199
    }
200
201
    /**
202
     * The user selected a category in the menu.
203
     *
204
     * @param int $category
205
     *
206
     * @return void
207
     */
208
    public function select(int $category): void
209
    {
210
        $this->category = $category;
211
212
        // Check if the category exist, else set the all categories.
213
        if ($this->categories->has($category) === false) {
214
            $this->category = 0;
215
        }
216
217
        // We close the menu after selected a category.
218
        if ($this->open == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
219
            $this->open = false;
220
        }
221
    }
222
223
    /**
224
     *  Check the value received by the front if it's a valid value, else set the default value.
225
     *
226
     * @param mixed $limit
227
     *
228
     * @return void
229
     */
230
    public function updatedLimit(int $limit): void
231
    {
232
        // Set the limit to the default config if the limit is not in the array.
233
        // Prevent people that modify the HTML value of the <option> to set a high value.
234
        if (!in_array($limit, $this->perPage)) {
235
            $this->limit = config('xetaravel.pagination.discuss.conversation_per_page');
236
        }
237
    }
238
239
    /**
240
     * Filter the field regarding the allowed fields.
241
     *
242
     * @param string $field
243
     *
244
     * @return void
245
     */
246
    public function updatedSortField(string $field): void
247
    {
248
        if (!in_array($field, $this->allowedFields)) {
249
            $this->sortField = 'created_at';
250
        }
251
    }
252
}
253