Completed
Push — master ( c7e879...390e33 )
by Fèvre
02:26
created

DiscussConversation::getPostsWithLogs()   D

Complexity

Conditions 10
Paths 30

Size

Total Lines 41
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 4.8196
c 0
b 0
f 0
cc 10
eloc 21
nc 30
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\DiscussConversationPresenter;
13
use Xetaravel\Models\Repositories\DiscussPostRepository;
14
use Xetaravel\Models\Scopes\DisplayScope;
15
use Xetaravel\Models\User;
16
17
class DiscussConversation extends Model
18
{
19
    use Countable,
20
        Sluggable,
21
        FloodGate,
22
        DiscussConversationPresenter,
23
        HasMentionsTrait;
24
25
    /**
26
     * The attributes that are mass assignable.
27
     *
28
     * @var array
29
     */
30
    protected $fillable = [
31
        'user_id',
32
        'category_id',
33
        'title',
34
        'slug',
35
        'post_count',
36
        'participants_count',
37
        'is_locked',
38
        'is_pinned',
39
        'is_solved',
40
        'is_edited',
41
        'edit_count'
42
    ];
43
44
    /**
45
     * The accessors to append to the model's array form.
46
     *
47
     * @var array
48
     */
49
    protected $appends = [
50
        'conversation_url',
51
        'last_page'
52
    ];
53
54
    /**
55
     * The attributes that should be mutated to dates.
56
     *
57
     * @var array
58
     */
59
    protected $dates = [
60
        'edited_at'
61
    ];
62
63
    /**
64
     * The "booting" method of the model.
65
     *
66
     * @return void
67
     */
68
    protected static function boot()
69
    {
70
        parent::boot();
71
72
        // Generated the slug before updating.
73
        static::updating(function ($model) {
74
            $model->generateSlug();
75
        });
76
77
        // Set the user id to the new conversation before saving it.
78
        static::creating(function ($model) {
79
            $model->user_id = Auth::id();
80
        });
81
    }
82
83
    /**
84
     * Return the field to slug.
85
     *
86
     * @return string
87
     */
88
    public function slugStrategy(): string
89
    {
90
        return 'title';
91
    }
92
93
    /**
94
     * Return the count cache configuration.
95
     *
96
     * @return array
97
     */
98
    public function countCaches(): array
99
    {
100
        return [
101
            'discuss_conversation_count' => [User::class, 'user_id', 'id'],
102
            'conversation_count' => [DiscussCategory::class, 'category_id', 'id']
103
        ];
104
    }
105
106
    /**
107
     * Get the category that owns the conversation.
108
     *
109
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
110
     */
111
    public function category()
112
    {
113
        return $this->belongsTo(DiscussCategory::class);
114
    }
115
116
    /**
117
     * Get the user that owns the conversation.
118
     *
119
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
120
     */
121
    public function user()
122
    {
123
        return $this->belongsTo(User::class);
124
    }
125
126
    /**
127
     * Get the posts for the conversation.
128
     *
129
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
130
     */
131
    public function posts()
132
    {
133
        return $this->hasMany(DiscussPost::class, 'conversation_id', 'id');
134
    }
135
136
    /**
137
     * Get the users for the conversation.
138
     *
139
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
140
     */
141
    public function users()
142
    {
143
        return $this->hasMany(DiscussUser::class, 'conversation_id', 'id');
144
    }
145
146
    /**
147
     * Get the first post of the conversation.
148
     *
149
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
150
     */
151
    public function firstPost()
152
    {
153
        return $this->hasOne(DiscussPost::class, 'id', 'first_post_id');
154
    }
155
156
    /**
157
     * Get the solved post of the conversation.
158
     *
159
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
160
     */
161
    public function solvedPost()
162
    {
163
        return $this->hasOne(DiscussPost::class, 'id', 'solved_post_id');
164
    }
165
166
    /**
167
     * Get the last post of the conversation.
168
     *
169
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
170
     */
171
    public function lastPost()
172
    {
173
        return $this->hasOne(DiscussPost::class, 'id', 'last_post_id');
174
    }
175
176
    /**
177
     * Get the user that edited the conversation.
178
     *
179
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
180
     */
181
    public function editedUser()
182
    {
183
        return $this->hasOne(User::class, 'id', 'edited_user_id');
184
    }
185
186
    /**
187
     * Get the discuss logs for the conversation.
188
     *
189
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
190
     */
191
    public function discussLogs()
192
    {
193
        return $this->morphMany(DiscussLog::class, 'loggable');
194
    }
195
196
    /**
197
     * Get the logs and posts related to the current conversation
198
     * for the given the pagination posts and return the data
199
     * ordered by `created_at` as a Collection.
200
     *
201
     * @param \Illuminate\Support\Collection $posts
202
     * @param int $page
203
     *
204
     * @return \Illuminate\Support\Collection
205
     */
206
    public function getPostsWithLogs(Collection $posts, int $page): Collection
207
    {
208
        $logs = DiscussLog::where([
209
            'loggable_type' => get_class($this),
210
            'loggable_id' => $this->getKey(),
211
        ]);
212
213
        if (!$posts->isEmpty()) {
214
            $previousPost = DiscussPostRepository::findPreviousPost($posts->first());
215
        }
216
217
        // When there're several pages and the current page is not the first and not the last.
218
        if ($this->lastPage > $page && $page !== 1) {
219
            $logs = $logs->where('created_at', '<=', $posts->last()->created_at)
220
                ->where('created_at', '>=', $previousPost->created_at);
0 ignored issues
show
Bug introduced by
The variable $previousPost does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
221
222
        // When there're only one page.
223
        } elseif ($this->lastPage == 1) {
224
            $logs = $logs->where('created_at', '>=', $this->created_at);
225
226
        // When there're several pages and the current page is the first page.
227
        } elseif ($page == 1) {
228
            $logs = $logs->where('created_at', '<=', $posts->last()->created_at);
229
230
        // When there're several page and the current page is the last page
231
        } elseif ($page == $this->lastPage) {
232
            $logs = $logs->where('created_at', '>', $previousPost->created_at);
233
        }
234
        $postsWithLogs = $posts->merge($logs->get())->sortBy('created_at');
235
236
        // If the conversation has a solved post, prepend it
237
        // then prepend the first post to the collection
238
        if ($this->lastPage == 1 || $page == 1) {
239
            if (!is_null($this->solved_post_id)) {
240
                $postsWithLogs->prepend(DiscussPost::findOrFail($this->solved_post_id));
241
            }
242
            $postsWithLogs->prepend(DiscussPost::findOrFail($this->first_post_id));
243
        }
244
245
        return $postsWithLogs;
246
    }
247
}
248