Passed
Push — master ( 4708a1...2e0f39 )
by Younes
02:12
created

Voteable::getVoteBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace Yoeunes\Voteable\Traits;
4
5
use Yoeunes\Voteable\VoteBuilder;
6
use Yoeunes\Voteable\Models\Vote;
7
use Illuminate\Support\Facades\DB;
8
use Illuminate\Database\Eloquent\Builder;
9
use Illuminate\Database\Query\JoinClause;
10
use Illuminate\Database\Eloquent\Relations\Relation;
11
12
trait Voteable
13
{
14
    /**
15
     * This model has many votes.
16
     *
17
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
18
     */
19
    public function votes()
20
    {
21
        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...
22
    }
23
24
    /**
25
     * @return mixed
26
     */
27
    public function upVotesCount()
28
    {
29
        return $this->votes()->where('amount', '>=', 0)->sum('amount');
30
    }
31
32
    /**
33
     * @return mixed
34
     */
35
    public function downVotesCount()
36
    {
37
        return $this->votes()->where('amount', '<', 0)->sum('amount');
38
    }
39
40
    /**
41
     * @return bool
42
     */
43
    public function isUpVoted()
44
    {
45
        return $this->votes()->where('amount', '>=', 0)->exists();
46
    }
47
48
    /**
49
     * @return bool
50
     */
51
    public function isDownVoted()
52
    {
53
        return $this->votes()->where('amount', '<', 0)->exists();
54
    }
55
56
    public function isVotedByUser(int $user_id)
57
    {
58
        return $this->votes()->where('user_id', $user_id)->exists();
59
    }
60
61
    /**
62
     * @param int $user_id
63
     *
64
     * @return bool
65
     */
66
    public function isUpVotedByUser(int $user_id)
67
    {
68
        return $this->votes()->where('amount', '>=', 0)->where('user_id', $user_id)->exists();
69
    }
70
71
    /**
72
     * @param int $user_id
73
     *
74
     * @return bool
75
     */
76
    public function isDownVotedByUser(int $user_id)
77
    {
78
        return $this->votes()->where('amount', '<', 0)->where('user_id', $user_id)->exists();
79
    }
80
81
    /**
82
     * @param Builder $query
83
     * @param string $direction
84
     * @param string $type
85
     *
86
     * @return Builder
87
     */
88
    public function scopeOrderByUpVotes(Builder $query, string $direction = 'asc', string $type = '>=')
89
    {
90
        return $query
91
            ->leftJoin('votes', function (JoinClause $join) {
92
                $join
93
                    ->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...
94
                    ->where('votes.voteable_type', Relation::getMorphedModel(__CLASS__) ?? __CLASS__);
95
            })
96
            ->where('amount', $type, 0)
97
            ->addSelect(DB::raw('SUM(votes.value) as count_votes'))
98
            ->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...
99
            ->orderBy('count_votes', $direction);
100
    }
101
102
    /**
103
     * @param Builder $query
104
     * @param string $direction
105
     *
106
     * @return Builder
107
     */
108
    public function scopeOrderByDownVotes(Builder $query, string $direction = 'asc')
109
    {
110
        return $this->scopeOrderByUpVotes($query, $direction, '<');
111
    }
112
113
    /**
114
     * @param int $vote_id
115
     *
116
     * @return mixed
117
     */
118
    public function cancelVote(int $vote_id)
119
    {
120
        return $this->votes()->where('id', $vote_id)->delete();
121
    }
122
123
    /**
124
     * @return mixed
125
     */
126
    public function resetVotes()
127
    {
128
        return $this->votes()->delete();
129
    }
130
131
    /**
132
     * @param int $user_id
133
     *
134
     * @return mixed
135
     */
136
    public function cancelVotesForUser(int $user_id)
137
    {
138
        return $this->votes()->where('user_id', $user_id)->delete();
139
    }
140
141
    /**
142
     * @param int $user_id
143
     * @param int $amount
144
     *
145
     * @return int
146
     */
147
    public function updateVotesForUser(int $user_id, int $amount)
148
    {
149
        return $this->votes()->where('user_id', $user_id)->update(['amount' => $amount]);
150
    }
151
152
    /**
153
     * @param int $vote_id
154
     * @param int $amount
155
     *
156
     * @return int
157
     */
158
    public function updateVote(int $vote_id, int $amount)
159
    {
160
        return $this->votes()->where('id', $vote_id)->update(['amount' => $amount]);
161
    }
162
163
    /**
164
     * @return VoteBuilder
165
     *
166
     * @throws \Throwable
167
     */
168
    public function getVoteBuilder()
169
    {
170
        return (new VoteBuilder())
171
            ->voteable($this);
172
    }
173
174
    public function voters()
175
    {
176
        /** @var Builder $query */
177
        $query = $this->hasManyThrough(config('voteable.user'), Vote::class, 'voteable_id', 'id');
0 ignored issues
show
Bug introduced by
It seems like hasManyThrough() 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...
178
179
        $query->getQuery()->where('votes.voteable_type', __CLASS__);
180
181
        return $query;
182
    }
183
}
184