Completed
Pull Request — master (#34)
by Fèvre
06:24 queued 03:17
created

DiscussThread::getCommentWithLogs()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 35
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 35
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 19
nc 6
nop 2
1
<?php
2
namespace Xetaravel\Models;
3
4
use Eloquence\Behaviours\CountCache\Countable;
5
use Eloquence\Behaviours\Sluggable;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Facades\App;
8
use Illuminate\Support\Facades\Auth;
9
use Illuminate\Support\Facades\Route;
10
use Xetaio\Mentions\Models\Traits\HasMentionsTrait;
11
use Xetaravel\Models\Gates\FloodGate;
12
use Xetaravel\Models\Presenters\DiscussThreadPresenter;
13
use Xetaravel\Models\Scopes\DisplayScope;
14
use Xetaravel\Models\User;
15
16
class DiscussThread extends Model
17
{
18
    use Countable,
19
        Sluggable,
20
        FloodGate,
21
        DiscussThreadPresenter,
22
        HasMentionsTrait;
23
24
    /**
25
     * The attributes that are mass assignable.
26
     *
27
     * @var array
28
     */
29
    protected $fillable = [
30
        'user_id',
31
        'category_id',
32
        'title',
33
        'slug',
34
        'content',
35
        'comment_count',
36
        'is_locked',
37
        'is_pinned',
38
        'is_solved',
39
        'is_edited'
40
    ];
41
42
    /**
43
     * The accessors to append to the model's array form.
44
     *
45
     * @var array
46
     */
47
    protected $appends = [
48
        'thread_url',
49
        'last_page'
50
    ];
51
52
    /**
53
     * The attributes that should be mutated to dates.
54
     *
55
     * @var array
56
     */
57
    protected $dates = [
58
        'edited_at'
59
    ];
60
61
    /**
62
     * The "booting" method of the model.
63
     *
64
     * @return void
65
     */
66
    protected static function boot()
67
    {
68
        parent::boot();
69
70
        // Generated the slug before updating.
71
        static::updating(function ($model) {
72
            $model->generateSlug();
73
        });
74
75
        // Set the user id to the new thread before saving it.
76
        static::creating(function ($model) {
77
            $model->user_id = Auth::id();
78
        });
79
    }
80
81
    /**
82
     * Return the field to slug.
83
     *
84
     * @return string
85
     */
86
    public function slugStrategy(): string
87
    {
88
        return 'title';
89
    }
90
91
    /**
92
     * Return the count cache configuration.
93
     *
94
     * @return array
95
     */
96
    public function countCaches(): array
97
    {
98
        return [
99
            'discuss_thread_count' => [User::class, 'user_id', 'id'],
100
            'thread_count' => [DiscussCategory::class, 'category_id', 'id']
101
        ];
102
    }
103
104
    /**
105
     * Get the category that owns the thread.
106
     *
107
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
108
     */
109
    public function category()
110
    {
111
        return $this->belongsTo(DiscussCategory::class);
112
    }
113
114
    /**
115
     * Get the user that owns the thread.
116
     *
117
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
118
     */
119
    public function user()
120
    {
121
        return $this->belongsTo(User::class);
122
    }
123
124
    /**
125
     * Get the comments for the thread.
126
     *
127
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
128
     */
129
    public function comments()
130
    {
131
        return $this->hasMany(DiscussComment::class, 'thread_id', 'id');
132
    }
133
134
    /**
135
     * Get the solved comment of the thread.
136
     *
137
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
138
     */
139
    public function solvedComment()
140
    {
141
        return $this->hasOne(DiscussComment::class, 'id', 'solved_comment_id');
142
    }
143
144
    /**
145
     * Get the last comment of the thread.
146
     *
147
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
148
     */
149
    public function lastComment()
150
    {
151
        return $this->hasOne(DiscussComment::class, 'id', 'last_comment_id');
152
    }
153
154
    /**
155
     * Get the user that edited the thread.
156
     *
157
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
158
     */
159
    public function editedUser()
160
    {
161
        return $this->hasOne(User::class, 'id', 'edited_user_id');
162
    }
163
164
    /**
165
     * Get the discuss logs for the thread.
166
     *
167
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
168
     */
169
    public function discussLogs()
170
    {
171
        return $this->morphMany(DiscussLog::class, 'loggable');
172
    }
173
174
    /**
175
     * Get the logs and comments related to the current thread
176
     * for the given the pagination comments and return the data
177
     * ordered by `created_at` as a Collection.
178
     *
179
     * @param \Illuminate\Support\Collection $comments
180
     * @param int $page
181
     *
182
     * @return \Illuminate\Support\Collection
183
     */
184
    public function getCommentWithLogs(Collection $comments, int $page): Collection
185
    {
186
        $logs = DiscussLog::where([
187
            'loggable_type' => get_class($this),
188
            'loggable_id' => $this->getKey(),
189
        ]);
190
191
        if ($comments->isEmpty()) {
192
            return $comments->merge($logs->get())->sortBy('created_at');
193
        }
194
        $previousComment = $this->getPreviousComment($comments->last()->created_at);
195
196
        // When there're several pages and the current page is not the first and not the last.
197
        if ($this->lastPage > $page && $page !== 1) {
198
            $logs = $logs->where('created_at', '<=', $comments->last()->created_at)
199
                ->where('created_at', '>=', $previousComment->created_at);
200
201
        // When there're only one page.
202
        } elseif ($this->lastPage == 1) {
203
            $logs = $logs->where('created_at', '>=', $this->created_at);
204
205
        // When there're several pages and the current page is the first page.
206
        } elseif ($page == 1) {
207
            $logs = $logs->where('created_at', '<=', $comments->last()->created_at);
208
209
        // When there're several page and the current page is the last page
210
        } elseif ($page == $this->lastPage) {
211
            $logs = $logs->where('created_at', '>=', $previousComment->created_at);
212
        }
213
        $logs = $logs->get();
214
215
        $commentsWithLogs = $comments->merge($logs);
216
217
        return $commentsWithLogs->sortBy('created_at');
218
    }
219
220
    /**
221
     * Get the previous comment related to the current thread with
222
     * the given date.
223
     *
224
     * @param string $createdAt
225
     *
226
     * @return \Xetaravel\Models\DiscussComment|null
227
     */
228
    protected function getPreviousComment(string $createdAt)
229
    {
230
        return DiscussComment::where('id', '!=', $this->solved_comment_id)
231
                ->where('created_at', '<', $createdAt)
232
                ->orderBy('created_at', 'desc')
233
                ->first();
234
    }
235
}
236