Completed
Push — master ( e10162...d4f9c3 )
by Younes
01:48
created

Voteable::votesCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Yoeunes\Voteable\Traits;
4
5
use Carbon\Carbon;
6
use Yoeunes\Voteable\Models\Vote;
7
use Yoeunes\Voteable\VoteBuilder;
8
use Illuminate\Support\Facades\DB;
9
use Illuminate\Database\Eloquent\Builder;
10
use Illuminate\Database\Query\JoinClause;
11
use Illuminate\Database\Eloquent\Relations\Relation;
12
13
trait Voteable
14
{
15
    /**
16
     * This model has many votes.
17
     *
18
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
19
     */
20
    public function votes()
21
    {
22
        return $this->morphMany(Vote::class, 'voteable');
0 ignored issues
show
Bug introduced by
It seems like morphMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
23
    }
24
25
    public function votesCount()
26
    {
27
        return $this->votes()->sum('amount');
28
    }
29
30
    /**
31
     * @return mixed
32
     */
33
    public function upVotesCount()
34
    {
35
        return $this->votes()->where('amount', '>=', 0)->sum('amount');
36
    }
37
38
    /**
39
     * @return mixed
40
     */
41
    public function downVotesCount()
42
    {
43
        return $this->votes()->where('amount', '<', 0)->sum('amount');
44
    }
45
46
    /**
47
     * @return bool
48
     */
49
    public function isUpVoted()
50
    {
51
        return $this->votes()->where('amount', '>=', 0)->exists();
52
    }
53
54
    /**
55
     * @return bool
56
     */
57
    public function isDownVoted()
58
    {
59
        return $this->votes()->where('amount', '<', 0)->exists();
60
    }
61
62
    public function isVotedByUser(int $user_id)
63
    {
64
        return $this->votes()->where('user_id', $user_id)->exists();
65
    }
66
67
    /**
68
     * @param int $user_id
69
     *
70
     * @return bool
71
     */
72
    public function isUpVotedByUser(int $user_id)
73
    {
74
        return $this->votes()->where('amount', '>=', 0)->where('user_id', $user_id)->exists();
75
    }
76
77
    /**
78
     * @param int $user_id
79
     *
80
     * @return bool
81
     */
82
    public function isDownVotedByUser(int $user_id)
83
    {
84
        return $this->votes()->where('amount', '<', 0)->where('user_id', $user_id)->exists();
85
    }
86
87
    /**
88
     * @param Builder $query
89
     * @param string $direction
90
     * @param string $type
91
     *
92
     * @return Builder
93
     */
94
    public function scopeOrderByUpVotes(Builder $query, string $direction = 'asc', string $type = '>=')
95
    {
96
        return $query
97
            ->leftJoin('votes', function (JoinClause $join) {
98
                $join
99
                    ->on('votes.voteable_id', $this->getTable() . '.id')
0 ignored issues
show
Bug introduced by
It seems like getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
100
                    ->where('votes.voteable_type', Relation::getMorphedModel(__CLASS__) ?? __CLASS__);
101
            })
102
            ->where('amount', $type, 0)
103
            ->addSelect(DB::raw('SUM(votes.value) as count_votes'))
104
            ->groupBy($this->getTable(). '.id')
0 ignored issues
show
Bug introduced by
It seems like getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
105
            ->orderBy('count_votes', $direction);
106
    }
107
108
    /**
109
     * @param Builder $query
110
     * @param string $direction
111
     *
112
     * @return Builder
113
     */
114
    public function scopeOrderByDownVotes(Builder $query, string $direction = 'asc')
115
    {
116
        return $this->scopeOrderByUpVotes($query, $direction, '<');
117
    }
118
119
    /**
120
     * @param int $vote_id
121
     *
122
     * @return mixed
123
     */
124
    public function cancelVote(int $vote_id)
125
    {
126
        return $this->votes()->where('id', $vote_id)->delete();
127
    }
128
129
    /**
130
     * @return mixed
131
     */
132
    public function resetVotes()
133
    {
134
        return $this->votes()->delete();
135
    }
136
137
    /**
138
     * @param int $user_id
139
     *
140
     * @return mixed
141
     */
142
    public function cancelVotesForUser(int $user_id)
143
    {
144
        return $this->votes()->where('user_id', $user_id)->delete();
145
    }
146
147
    /**
148
     * @param int $user_id
149
     * @param int $amount
150
     *
151
     * @return int
152
     */
153
    public function updateVotesForUser(int $user_id, int $amount)
154
    {
155
        return $this->votes()->where('user_id', $user_id)->update(['amount' => $amount]);
156
    }
157
158
    /**
159
     * @param int $vote_id
160
     * @param int $amount
161
     *
162
     * @return int
163
     */
164
    public function updateVote(int $vote_id, int $amount)
165
    {
166
        return $this->votes()->where('id', $vote_id)->update(['amount' => $amount]);
167
    }
168
169
    /**
170
     * @return VoteBuilder
171
     *
172
     * @throws \Throwable
173
     */
174
    public function getVoteBuilder()
175
    {
176
        return (new VoteBuilder())
177
            ->voteable($this);
178
    }
179
180
    public function voters()
181
    {
182
        return $this->morphToMany(config('voteable.user'), 'voteable', 'votes');
0 ignored issues
show
Bug introduced by
It seems like morphToMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
183
    }
184
185
    public function countVotesByDate($from, $to)
186
    {
187
        $range = [(new Carbon($from))->startOfDay(), (new Carbon($to))->endOfDay()];
188
189
        return $this->votes()->whereBetween('created_at', $range)->sum('amount');
190
    }
191
}
192