Completed
Push — master ( a97ac2...11944e )
by Younes
01:48
created

Voteable::scopeOrderByVotes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 2
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Yoeunes\Voteable\Traits;
4
5
use Yoeunes\Voteable\Models\Vote;
6
use Yoeunes\Voteable\VoteBuilder;
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
use Yoeunes\Voteable\VoteQueryBuilder;
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
    public function isVoted()
47
    {
48
        return $this->votes()->exists();
49
    }
50
51
    /**
52
     * @return bool
53
     */
54
    public function isUpVoted()
55
    {
56
        return $this->votes()->where('amount', '>=', 0)->exists();
57
    }
58
59
    /**
60
     * @return bool
61
     */
62
    public function isDownVoted()
63
    {
64
        return $this->votes()->where('amount', '<', 0)->exists();
65
    }
66
67
    public function isVotedByUser(int $user_id)
68
    {
69
        return $this->votes()->where('user_id', $user_id)->exists();
70
    }
71
72
    /**
73
     * @param int $user_id
74
     *
75
     * @return bool
76
     */
77
    public function isUpVotedByUser(int $user_id)
78
    {
79
        return $this->votes()->where('amount', '>=', 0)->where('user_id', $user_id)->exists();
80
    }
81
82
    /**
83
     * @param int $user_id
84
     *
85
     * @return bool
86
     */
87
    public function isDownVotedByUser(int $user_id)
88
    {
89
        return $this->votes()->where('amount', '<', 0)->where('user_id', $user_id)->exists();
90
    }
91
92
    /**
93
     * @param Builder $query
94
     * @param string $direction
95
     * @param string $type
0 ignored issues
show
Bug introduced by
There is no parameter named $type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
96
     *
97
     * @return Builder
98
     */
99
    public function scopeOrderByVotes(Builder $query, string $direction = 'asc')
100
    {
101
        return $query
102
            ->leftJoin('votes', function (JoinClause $join) {
103
                $join
104
                    ->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...
105
                    ->where('votes.voteable_type', Relation::getMorphedModel(__CLASS__) ?? __CLASS__);
106
            })
107
            ->addSelect(DB::raw('SUM(votes.value) as count_votes'))
108
            ->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...
109
            ->orderBy('count_votes', $direction);
110
    }
111
112
    /**
113
     * @param Builder $query
114
     * @param string $direction
115
     * @param string $type
116
     *
117
     * @return Builder
118
     */
119
    public function scopeOrderByUpVotes(Builder $query, string $direction = 'asc', string $type = '>=')
120
    {
121
        return $query
122
            ->leftJoin('votes', function (JoinClause $join) {
123
                $join
124
                    ->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...
125
                    ->where('votes.voteable_type', Relation::getMorphedModel(__CLASS__) ?? __CLASS__);
126
            })
127
            ->where('amount', $type, 0)
128
            ->addSelect(DB::raw('SUM(votes.value) as count_votes'))
129
            ->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...
130
            ->orderBy('count_votes', $direction);
131
    }
132
133
    /**
134
     * @param Builder $query
135
     * @param string $direction
136
     *
137
     * @return Builder
138
     */
139
    public function scopeOrderByDownVotes(Builder $query, string $direction = 'asc')
140
    {
141
        return $this->scopeOrderByUpVotes($query, $direction, '<');
142
    }
143
144
    /**
145
     * @param int $vote_id
146
     *
147
     * @return mixed
148
     */
149
    public function cancelVote(int $vote_id)
150
    {
151
        return $this->votes()->where('id', $vote_id)->delete();
152
    }
153
154
    /**
155
     * @return mixed
156
     */
157
    public function resetVotes()
158
    {
159
        return $this->votes()->delete();
160
    }
161
162
    /**
163
     * @param int $user_id
164
     *
165
     * @return mixed
166
     */
167
    public function cancelVotesForUser(int $user_id)
168
    {
169
        return $this->votes()->where('user_id', $user_id)->delete();
170
    }
171
172
    /**
173
     * @param int $user_id
174
     * @param int $amount
175
     *
176
     * @return int
177
     */
178
    public function updateVotesForUser(int $user_id, int $amount)
179
    {
180
        return $this->votes()->where('user_id', $user_id)->update(['amount' => $amount]);
181
    }
182
183
    /**
184
     * @param int $vote_id
185
     * @param int $amount
186
     *
187
     * @return int
188
     */
189
    public function updateVote(int $vote_id, int $amount)
190
    {
191
        return $this->votes()->where('id', $vote_id)->update(['amount' => $amount]);
192
    }
193
194
    /**
195
     * @return VoteBuilder
196
     *
197
     * @throws \Throwable
198
     */
199
    public function getVoteBuilder()
200
    {
201
        return (new VoteBuilder())
202
            ->voteable($this);
203
    }
204
205
    /**
206
     * @return VoteQueryBuilder
207
     *
208
     * @throws \Throwable
209
     */
210
    public function getVoteQueryBuilder()
211
    {
212
        return (new VoteQueryBuilder($this->votes()));
213
    }
214
215
    public function voters()
216
    {
217
        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...
218
    }
219
220
    public function countVotesByDate($from = null, $to = null)
221
    {
222
        $query = $this->votes();
223
224
        if (! empty($from) && empty($to)) {
225
            $query->where('created_at', '>=', date_transformer($from));
226
        } elseif (empty($from) && ! empty($to)) {
227
            $query->where('created_at', '<=', date_transformer($to));
228
        } elseif (! empty($from) && ! empty($to)) {
229
            $query->whereBetween('created_at', [date_transformer($from), date_transformer($to)]);
230
        }
231
232
        return $query->sum('amount');
233
    }
234
}
235