Passed
Push — 5.0.0 ( 746f48...fc989a )
by Fèvre
06:29
created

Conversation::getRowsQueryProperty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 17
rs 9.9332
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Xetaravel\Livewire\Discuss;
6
7
use Illuminate\Contracts\Database\Query\Builder;
8
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
9
use Illuminate\Pagination\LengthAwarePaginator;
10
use Illuminate\Support\Collection;
11
use Livewire\Attributes\Url;
12
use Livewire\Component;
13
use Masmerise\Toaster\Toastable;
14
use Psr\Container\ContainerExceptionInterface;
15
use Psr\Container\NotFoundExceptionInterface;
16
use Xetaravel\Livewire\Traits\WithCachedRows;
17
use Xetaravel\Livewire\Traits\WithSorting;
18
use Xetaravel\Models\DiscussCategory;
19
use Xetaravel\Models\DiscussConversation;
20
21
class Conversation extends Component
22
{
23
    use AuthorizesRequests;
24
    use Toastable;
25
    use WithCachedRows;
26
    use WithSorting;
27
28
    /**
29
     * Categories used for sorting.
30
     *
31
     * @var Collection
32
     */
33
    public Collection $categories;
34
35
    /**
36
     * The default number used to limit conversations per page.
37
     *
38
     * @var int[]
39
     */
40
    public array $perPage = [
41
        10,
42
        25,
43
        50
44
    ];
45
46
    /**
47
     * The field to sort by.
48
     *
49
     * @var string
50
     */
51
    #[Url(as: 'f', except: 'created_at')]
52
    public string $sortField = 'created_at';
53
54
    /**
55
     * The direction of the ordering.
56
     *
57
     * @var string
58
     */
59
    #[Url(as: 'd')]
60
    public string $sortDirection = 'desc';
61
62
    /**
63
     * The number of conversation limited per page.
64
     *
65
     * @var null|int
66
     */
67
    #[Url(as: 'l', except: 15)]
68
    public ?int $limit = null;
69
70
    /**
71
     * The category selected in the select menu.
72
     *
73
     * 0 = all categories
74
     *
75
     * @var int
76
     */
77
    #[Url(as: 'c', except: 0)]
78
    public int $category = 0;
79
80
    /**
81
     * The string to search.
82
     *
83
     * @var string
84
     */
85
    #[Url(as: 's', except: '')]
86
    public string $search = '';
87
88
    /**
89
     * Array of allowed fields.
90
     *
91
     * @var array
92
     */
93
    public array $allowedFields = [
94
        'post_count',
95
        'is_locked',
96
        'is_solved',
97
        'created_at'
98
    ];
99
100
    /**
101
     * Tell if the categories select menu is open or not.
102
     *
103
     * @var bool
104
     */
105
    public $open = false;
106
107
    public function mount(): void
108
    {
109
        // Create the categories list for the select and push the `All Categories` into it at the first position.
110
        $categories = collect();
111
        $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

111
        $categories->push(/** @scrutinizer ignore-type */ [
Loading history...
112
            'id' => 0,
113
            'icon' => 'fas-list',
114
            'title' => 'All Categories',
115
            'color' => 'currentColor'
116
        ]);
117
118
        // Get and push all the discuss categories.
119
        $categoriesAll = DiscussCategory::orderBy('id')->get();
120
        $categoriesAll->each(function ($item) use ($categories) {
121
            $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

121
            $categories->push(/** @scrutinizer ignore-type */ [
Loading history...
122
                'id' => $item->id,
123
                'icon' => $item->icon,
124
                'title' => $item->title,
125
                'color' => $item->color
126
            ]);
127
        });
128
        // Reorder the collection by `id` key and convert to array.
129
        $this->categories = $categories->keyBy('id');
130
131
        // Add the default perPage setting to the array.
132
        $this->perPage[] = config('xetaravel.pagination.discuss.conversation_per_page');
133
        // Re-order the array by `asc`.
134
        sort($this->perPage);
135
136
        // Set the limit to the default config if the limit is not in the array.
137
        if (!in_array($this->limit, $this->perPage)) {
138
            $this->limit = config('xetaravel.pagination.discuss.conversation_per_page');
139
        }
140
141
        // Check if the category exist, else set the all categories.
142
        if (!$this->categories->has($this->category)) {
143
            $this->category = 0;
144
        }
145
    }
146
147
    public function render()
148
    {
149
        return view('livewire.discuss.conversation', [
150
            'conversations' => $this->rows
0 ignored issues
show
Bug Best Practice introduced by
The property rows does not exist on Xetaravel\Livewire\Discuss\Conversation. Since you implemented __get, consider adding a @property annotation.
Loading history...
151
        ]);
152
    }
153
154
    /**
155
     * Create and return the query for the items.
156
     *
157
     * @return Builder
158
     */
159
    public function getRowsQueryProperty(): Builder
160
    {
161
        $query = DiscussConversation::query()
162
            ->with(['user', 'category', 'firstPost', 'lastPost', 'lastPost.user', 'lastPost.user.account', 'users', 'users.user', 'users.user.account'])
163
            ->when($this->search, function ($query, $search) {
164
                return $query->where('title', 'LIKE', '%' . $search . '%')
165
                    ->orWhereHas('posts', function ($query) use ($search) {
166
                        return $query->where('content', 'like', '%' . $search . '%');
167
                    });
168
            })
169
            // If the `category` == 0, we display all categories so no condition applied.
170
            ->when($this->category, function ($query, $category) {
171
                return $query->where('category_id', $category);
172
            })
173
            ->orderBy('is_pinned', 'desc');
174
175
        return $this->applySorting($query);
0 ignored issues
show
Bug introduced by
It seems like $query can also be of type Illuminate\Database\Eloq...gHasThroughRelationship; however, parameter $query of Xetaravel\Livewire\Discu...rsation::applySorting() does only seem to accept Illuminate\Contracts\Database\Query\Builder, 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

175
        return $this->applySorting(/** @scrutinizer ignore-type */ $query);
Loading history...
176
    }
177
178
    /**
179
     * Build the query and paginate it.
180
     *
181
     * @return LengthAwarePaginator
182
     *
183
     * @throws ContainerExceptionInterface
184
     * @throws NotFoundExceptionInterface
185
     */
186
    public function getRowsProperty(): LengthAwarePaginator
187
    {
188
        return $this->cache(function () {
189
            return $this->rowsQuery->paginate($this->limit);
0 ignored issues
show
Bug Best Practice introduced by
The property rowsQuery does not exist on Xetaravel\Livewire\Discuss\Conversation. Since you implemented __get, consider adding a @property annotation.
Loading history...
190
        });
191
    }
192
193
    /**
194
     *  Check the value received by the front if it's a valid value, else set the default value.
195
     *
196
     * @param mixed $limit
197
     *
198
     * @return void
199
     */
200
    public function updatedLimit(int $limit): void
201
    {
202
        // Set the limit to the default config if the limit is not in the array.
203
        // Prevent people that modify the HTML value of the <option> to set a high value.
204
        if (!in_array($limit, $this->perPage)) {
205
            $this->limit = config('xetaravel.pagination.discuss.conversation_per_page');
206
        }
207
    }
208
}
209