Passed
Push — 5.0.0 ( f07a46...357374 )
by Fèvre
05:39
created

DiscussConversation::casts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Xetaravel\Models;
6
7
use Eloquence\Behaviours\CountCache\CountedBy;
8
use Eloquence\Behaviours\CountCache\HasCounts;
9
use Eloquence\Behaviours\HasSlugs;
10
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
11
use Illuminate\Database\Eloquent\Relations\BelongsTo;
12
use Illuminate\Database\Eloquent\Relations\HasMany;
13
use Illuminate\Database\Eloquent\Relations\HasOne;
14
use Illuminate\Database\Eloquent\Relations\MorphMany;
15
use Illuminate\Support\Collection;
16
use Xetaio\Mentions\Models\Traits\HasMentionsTrait;
17
use Xetaravel\Models\Gates\FloodGate;
18
use Xetaravel\Models\Presenters\DiscussConversationPresenter;
19
use Xetaravel\Models\Repositories\DiscussPostRepository;
20
use Xetaravel\Observers\DiscussConversationObserver;
21
22
#[ObservedBy([DiscussConversationObserver::class])]
23
class DiscussConversation extends Model
24
{
25
    use DiscussConversationPresenter;
0 ignored issues
show
introduced by
The trait Xetaravel\Models\Present...ssConversationPresenter requires some properties which are not provided by Xetaravel\Models\DiscussConversation: $post_count, $slug, $post_count_formated, $is_solved
Loading history...
26
    use FloodGate;
27
    use HasCounts;
28
    use HasMentionsTrait;
29
    use HasSlugs;
30
31
    /**
32
     * The attributes that are mass assignable.
33
     *
34
     * @var array
35
     */
36
    protected $fillable = [
37
        'user_id',
38
        'category_id',
39
        'title',
40
        'slug',
41
        'post_count',
42
        'participants_count',
43
        'is_locked',
44
        'is_pinned',
45
        'is_solved',
46
        'is_edited',
47
        'edit_count'
48
    ];
49
50
    /**
51
     * The accessors to append to the model's array form.
52
     *
53
     * @var array
54
     */
55
    protected $appends = [
56
        'conversation_url',
57
        'last_page'
58
    ];
59
60
    /**
61
     * The attributes that should be cast.
62
     */
63
    protected function casts(): array
64
    {
65
        return [
66
            'edited_at' => 'datetime',
67
            'is_locked' => 'boolean',
68
            'is_pinned' => 'boolean',
69
            'is_solved' => 'boolean',
70
            'is_edited' => 'boolean',
71
        ];
72
    }
73
74
    /**
75
     * Return the field to slug.
76
     *
77
     * @return string
78
     */
79
    public function slugStrategy(): string
80
    {
81
        return 'title';
82
    }
83
84
    /**
85
     * Get the category that owns the conversation.
86
     *
87
     * @return BelongsTo
88
     */
89
    #[CountedBy(as: 'conversation_count')]
90
    public function category(): BelongsTo
91
    {
92
        return $this->belongsTo(DiscussCategory::class);
93
    }
94
95
    /**
96
     * Get the user that owns the conversation.
97
     *
98
     * @return BelongsTo
99
     */
100
    #[CountedBy(as: 'discuss_conversation_count')]
101
    public function user(): BelongsTo
102
    {
103
        return $this->belongsTo(User::class);
104
    }
105
106
    /**
107
     * Get the posts for the conversation.
108
     *
109
     * @return HasMany
110
     */
111
    public function posts(): HasMany
112
    {
113
        return $this->hasMany(DiscussPost::class, 'conversation_id', 'id');
114
    }
115
116
    /**
117
     * Get the users for the conversation.
118
     *
119
     * @return HasMany
120
     */
121
    public function users(): HasMany
122
    {
123
        return $this->hasMany(DiscussUser::class, 'conversation_id', 'id');
124
    }
125
126
    /**
127
     * Get the first post of the conversation.
128
     *
129
     * @return HasOne
130
     */
131
    public function firstPost(): HasOne
132
    {
133
        return $this->hasOne(DiscussPost::class, 'id', 'first_post_id');
134
    }
135
136
    /**
137
     * Get the solved post of the conversation.
138
     *
139
     * @return HasOne
140
     */
141
    public function solvedPost(): HasOne
142
    {
143
        return $this->hasOne(DiscussPost::class, 'id', 'solved_post_id');
144
    }
145
146
    /**
147
     * Get the last post of the conversation.
148
     *
149
     * @return HasOne
150
     */
151
    public function lastPost(): HasOne
152
    {
153
        return $this->hasOne(DiscussPost::class, 'id', 'last_post_id');
154
    }
155
156
    /**
157
     * Get the user that edited the conversation.
158
     *
159
     * @return HasOne
160
     */
161
    public function editedUser(): HasOne
162
    {
163
        return $this->hasOne(User::class, 'id', 'edited_user_id')->withTrashed();
164
    }
165
166
    /**
167
     * Get the discuss logs for the conversation.
168
     *
169
     * @return MorphMany
170
     */
171
    public function discussLogs(): MorphMany
172
    {
173
        return $this->morphMany(DiscussLog::class, 'loggable');
174
    }
175
176
    /**
177
     * Get the logs and posts related to the current conversation
178
     * for the given pagination posts and return the data
179
     * ordered by `created_at` as a Collection.
180
     *
181
     * @param Collection $posts
182
     * @param int $page
183
     *
184
     * @return Collection
185
     */
186
    public function getPostsWithLogs(Collection $posts, int $page): Collection
187
    {
188
        $logs = DiscussLog::where([
189
            'loggable_type' => get_class($this),
190
            'loggable_id' => $this->getKey(),
191
        ]);
192
193
        if (!$posts->isEmpty()) {
194
            $previousPost = DiscussPostRepository::findPreviousPost($posts->first());
195
        }
196
197
        // When there are several pages and the current page is not the first and not the last.
198
        if ($this->lastPage > $page && $page !== 1) {
199
            $logs = $logs->where('created_at', '<=', $posts->last()->created_at)
200
                ->where('created_at', '>=', $previousPost->created_at);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $previousPost does not seem to be defined for all execution paths leading up to this point.
Loading history...
201
202
            // When there are only one page.
203
        } elseif ($this->lastPage == 1) {
204
            $logs = $logs->where('created_at', '>=', $this->created_at);
205
206
            // When there are several pages and the current page is the first page.
207
        } elseif ($page == 1) {
208
            $logs = $logs->where('created_at', '<=', $posts->last()->created_at);
209
210
            // When there're several page and the current page is the last page
211
        } elseif ($page == $this->lastPage) {
212
            $logs = $logs->where('created_at', '>', $previousPost->created_at);
213
        }
214
        $postsWithLogs = $posts->merge($logs->get())->sortBy('created_at');
215
216
        // If the conversation has a solved post, prepend it
217
        // then prepend the first post to the collection
218
        if ($this->lastPage == 1 || $page == 1) {
219
            if (!is_null($this->solved_post_id)) {
0 ignored issues
show
introduced by
The condition is_null($this->solved_post_id) is always false.
Loading history...
220
                $postsWithLogs->prepend(DiscussPost::findOrFail($this->solved_post_id));
221
            }
222
            $postsWithLogs->prepend(DiscussPost::findOrFail($this->first_post_id));
223
        }
224
225
        return $postsWithLogs;
226
    }
227
}
228