DiscussConversation::editedUser()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
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
        'is_locked',
42
        'is_pinned',
43
        'is_solved',
44
    ];
45
46
    /**
47
     * The accessors to append to the model's array form.
48
     *
49
     * @var array
50
     */
51
    protected $appends = [
52
        'conversation_url',
53
        'last_page'
54
    ];
55
56
    /**
57
     * The attributes that should be cast.
58
     */
59
    protected function casts(): array
60
    {
61
        return [
62
            'is_locked' => 'boolean',
63
            'is_pinned' => 'boolean',
64
            'is_solved' => 'boolean',
65
            'is_edited' => 'boolean',
66
        ];
67
    }
68
69
    /**
70
     * Return the field to slug.
71
     *
72
     * @return string
73
     */
74
    public function slugStrategy(): string
75
    {
76
        return 'title';
77
    }
78
79
    /**
80
     * Get the category that owns the conversation.
81
     *
82
     * @return BelongsTo
83
     */
84
    #[CountedBy(as: 'conversation_count')]
85
    public function category(): BelongsTo
86
    {
87
        return $this->belongsTo(DiscussCategory::class);
88
    }
89
90
    /**
91
     * Get the user that owns the conversation.
92
     *
93
     * @return BelongsTo
94
     */
95
    #[CountedBy(as: 'discuss_conversation_count')]
96
    public function user(): BelongsTo
97
    {
98
        return $this->belongsTo(User::class)->withTrashed();
99
    }
100
101
    /**
102
     * Get the posts for the conversation.
103
     *
104
     * @return HasMany
105
     */
106
    public function posts(): HasMany
107
    {
108
        return $this->hasMany(DiscussPost::class, 'conversation_id', 'id');
109
    }
110
111
    /**
112
     * Get the users for the conversation.
113
     *
114
     * @return HasMany
115
     */
116
    public function users(): HasMany
117
    {
118
        return $this->hasMany(DiscussUser::class, 'conversation_id', 'id');
119
    }
120
121
    /**
122
     * Get the first post of the conversation.
123
     *
124
     * @return HasOne
125
     */
126
    public function firstPost(): HasOne
127
    {
128
        return $this->hasOne(DiscussPost::class, 'id', 'first_post_id');
129
    }
130
131
    /**
132
     * Get the solved post of the conversation.
133
     *
134
     * @return HasOne
135
     */
136
    public function solvedPost(): HasOne
137
    {
138
        return $this->hasOne(DiscussPost::class, 'id', 'solved_post_id');
139
    }
140
141
    /**
142
     * Get the last post of the conversation.
143
     *
144
     * @return HasOne
145
     */
146
    public function lastPost(): HasOne
147
    {
148
        return $this->hasOne(DiscussPost::class, 'id', 'last_post_id');
149
    }
150
151
    /**
152
     * Get the user that edited the conversation.
153
     *
154
     * @return HasOne
155
     */
156
    public function editedUser(): HasOne
157
    {
158
        return $this->hasOne(User::class, 'id', 'edited_user_id')->withTrashed();
159
    }
160
161
    /**
162
     * Get the discuss logs for the conversation.
163
     *
164
     * @return MorphMany
165
     */
166
    public function discussLogs(): MorphMany
167
    {
168
        return $this->morphMany(DiscussLog::class, 'loggable');
169
    }
170
171
    /**
172
     * Get the logs and posts related to the current conversation
173
     * for the given pagination posts and return the data
174
     * ordered by `created_at` as a Collection.
175
     *
176
     * @param Collection $posts
177
     * @param int $page
178
     *
179
     * @return Collection
180
     */
181
    public function getPostsWithLogs(Collection $posts, int $page): Collection
182
    {
183
        $logs = DiscussLog::query()
184
            ->with('user.account')
185
            ->where([
186
                'loggable_type' => get_class($this),
187
                'loggable_id' => $this->getKey(),
188
            ]);
189
190
        // When there are several pages and the current page is not the first and not the last.
191
        if ($this->lastPage > $page && $page !== 1) {
0 ignored issues
show
Bug introduced by
The property lastPage does not seem to exist on Xetaravel\Models\DiscussConversation. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
192
            $previousPost = DiscussPostRepository::findPreviousPost($posts->first());
193
194
            $logs = $logs
195
                ->where('created_at', '<=', $posts->last()->created_at)
196
                ->where('created_at', '>=', $previousPost->created_at);
197
198
            // When there are only one page.
199
        } elseif ($this->lastPage === 1) {
200
            $logs = $logs
201
                ->where('created_at', '>=', $this->created_at);
202
203
            // When there are several pages and the current page is the first page.
204
        } elseif ($page === 1) {
205
            $logs = $logs
206
                ->where('created_at', '<=', $posts->last()->created_at);
207
208
            // When there are several page and the current page is the last page
209
        } elseif ($page === $this->lastPage) {
210
            $previousPost = DiscussPostRepository::findPreviousPost($posts->first());
211
212
            $logs = $logs
213
                ->where('created_at', '>', $previousPost->created_at);
214
        }
215
        $postsWithLogs = $posts->merge($logs->get())->sortBy('created_at');
216
217
        // If the conversation has a solved post, prepend it
218
        // then prepend the first post to the collection
219
        if ($this->lastPage === 1 || $page === 1) {
220
            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...
221
                $postsWithLogs->prepend(DiscussPost::findOrFail($this->solved_post_id));
222
            }
223
            $postsWithLogs->prepend(DiscussPost::findOrFail($this->first_post_id));
224
        }
225
226
        return $postsWithLogs;
227
    }
228
}
229