1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Tinyissue package. |
5
|
|
|
* |
6
|
|
|
* (c) Mohamed Alsharaf <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Tinyissue\Model\Traits\Project; |
13
|
|
|
|
14
|
|
|
use Illuminate\Database\Eloquent; |
15
|
|
|
use Illuminate\Database\Eloquent\Relations; |
16
|
|
|
use Illuminate\Database\Eloquent\Relations\Relation; |
17
|
|
|
use Illuminate\Database\Query; |
18
|
|
|
use Tinyissue\Model\Project; |
19
|
|
|
use Tinyissue\Model\User; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* QueryTrait is trait class containing the database queries methods for the Project model. |
23
|
|
|
* |
24
|
|
|
* @author Mohamed Alsharaf <[email protected]> |
25
|
|
|
* |
26
|
|
|
* @property int $id |
27
|
|
|
* |
28
|
|
|
* @method Eloquent\Model where($column, $operator = null, $value = null, $boolean = 'and') |
29
|
|
|
* @method Query\Builder join($table, $one, $operator = null, $two = null, $type = 'inner', $where = false) |
30
|
|
|
* @method Relations\HasMany users() |
31
|
|
|
* @method Relations\HasMany issues() |
32
|
|
|
* @method void filterAssignTo(Query\Builder $query, $userId) |
33
|
|
|
* @method void filterTitleOrBody(Query\Builder $query, $keyword) |
34
|
|
|
* @method void filterTags(Eloquent\Builder $query, array $tags) |
35
|
|
|
* @method void sortByUpdated(Query\Builder $query, $order = 'asc') |
36
|
|
|
* @method Eloquent\Collection sortByTag(Query\Builder $query, $tagGroup, $order = 'asc') |
37
|
|
|
*/ |
38
|
|
|
trait QueryTrait |
39
|
|
|
{ |
40
|
|
|
/** |
41
|
|
|
* Returns collection of active projects. |
42
|
|
|
* |
43
|
|
|
* @return Eloquent\Collection |
44
|
|
|
*/ |
45
|
|
|
public static function activeProjects() |
46
|
|
|
{ |
47
|
|
|
return static::where('status', '=', Project::STATUS_OPEN) |
48
|
|
|
->orderBy('name', 'ASC') |
49
|
|
|
->get(); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Returns collection of public projects. |
54
|
|
|
* |
55
|
|
|
* @return Eloquent\Collection |
56
|
|
|
*/ |
57
|
|
|
public function publicProjects() |
58
|
|
|
{ |
59
|
|
|
return $this->where('private', '=', Project::PRIVATE_NO) |
60
|
|
|
->orderBy('name', 'ASC') |
61
|
|
|
->get(); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Returns all users that are not assigned in the current project. |
66
|
|
|
* |
67
|
|
|
* @return array |
68
|
|
|
*/ |
69
|
1 |
|
public function usersNotIn() |
70
|
|
|
{ |
71
|
1 |
|
if ($this->id > 0) { |
72
|
|
|
$userIds = $this->users()->lists('user_id')->all(); |
73
|
|
|
$users = User::where('deleted', '=', User::NOT_DELETED_USERS)->whereNotIn('id', $userIds)->get(); |
74
|
|
|
} else { |
75
|
1 |
|
$users = User::where('deleted', '=', User::NOT_DELETED_USERS)->get(); |
76
|
|
|
} |
77
|
|
|
|
78
|
1 |
|
return $users->lists('fullname', 'id')->all(); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Fetch and filter issues in the project. |
83
|
|
|
* |
84
|
|
|
* @param int $status |
85
|
|
|
* @param array $filter |
86
|
|
|
* |
87
|
|
|
* @return \Illuminate\Database\Eloquent\Collection |
88
|
|
|
*/ |
89
|
2 |
|
public function listIssues($status = Project\Issue::STATUS_OPEN, array $filter = []) |
90
|
|
|
{ |
91
|
2 |
|
$sortOrder = array_get($filter, 'sort.sortorder', 'desc'); |
92
|
2 |
|
$sortBy = array_get($filter, 'sort.sortby', null); |
93
|
|
|
|
94
|
2 |
|
$query = $this->issues() |
95
|
2 |
|
->with('countComments', 'user', 'updatedBy', 'tags', 'tags.parent') |
96
|
2 |
|
->with([ |
97
|
|
|
'tags' => function (Relation $query) use ($sortOrder) { |
98
|
2 |
|
$query->orderBy('name', $sortOrder); |
99
|
2 |
|
}, |
100
|
|
|
]) |
101
|
2 |
|
->where('status', '=', $status); |
102
|
|
|
|
103
|
|
|
// Filter issues |
104
|
2 |
|
$this->filterAssignTo($query, array_get($filter, 'assignto')); |
105
|
2 |
|
$this->filterTitleOrBody($query, array_get($filter, 'keyword')); |
106
|
2 |
|
$this->filterTags($query, array_get($filter, 'tag_status')); |
107
|
2 |
|
$this->filterTags($query, array_get($filter, 'tag_type')); |
108
|
|
|
|
109
|
|
|
// Sort |
110
|
2 |
|
if ($sortBy == 'updated') { |
111
|
|
|
$this->sortByUpdated($query, $sortOrder); |
112
|
2 |
|
} elseif (($tagGroup = substr($sortBy, strlen('tag:'))) > 0) { |
113
|
|
|
return $this->sortByTag($query, $tagGroup, $sortOrder); |
114
|
|
|
} |
115
|
|
|
|
116
|
2 |
|
return $query->get(); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Fetch issues assigned to a user. |
121
|
|
|
* |
122
|
|
|
* @param int $userId |
123
|
|
|
* |
124
|
|
|
* @return \Illuminate\Database\Eloquent\Collection |
125
|
|
|
*/ |
126
|
1 |
|
public function listAssignedIssues($userId) |
127
|
|
|
{ |
128
|
1 |
|
return $this->issues() |
129
|
1 |
|
->with('countComments', 'user', 'updatedBy') |
130
|
1 |
|
->where('status', '=', Project\Issue::STATUS_OPEN) |
131
|
1 |
|
->where('assigned_to', '=', $userId) |
132
|
1 |
|
->orderBy('updated_at', 'DESC') |
133
|
1 |
|
->get(); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Returns projects with issues details eager loaded. |
138
|
|
|
* |
139
|
|
|
* @param int $status |
140
|
|
|
* @param int $private |
141
|
|
|
* |
142
|
|
|
* @return Relations\HasMany |
143
|
|
|
*/ |
144
|
4 |
|
public function projectsWidthIssues($status = Project::STATUS_OPEN, $private = Project::PRIVATE_NO) |
145
|
|
|
{ |
146
|
|
|
$query = $this |
147
|
4 |
|
->where('status', '=', $status) |
148
|
4 |
|
->orderBy('name'); |
149
|
|
|
|
150
|
4 |
|
if ($private !== Project::PRIVATE_ALL) { |
151
|
4 |
|
$query->where('private', '=', $private); |
152
|
|
|
} |
153
|
|
|
|
154
|
4 |
|
$query->with([ |
155
|
|
View Code Duplication |
'issues' => function (Relations\Relation $query) use ($status) { |
|
|
|
|
156
|
3 |
|
$query->with('updatedBy'); |
157
|
3 |
|
if ($status === Project::STATUS_OPEN) { |
158
|
3 |
|
$query->where('status', '=', Project\Issue::STATUS_OPEN); |
159
|
|
|
} |
160
|
4 |
|
}, |
161
|
|
|
'issues.user' => function () { |
162
|
4 |
|
}, |
163
|
|
|
'issues.countComments' => function () { |
164
|
4 |
|
}, |
165
|
|
|
]); |
166
|
|
|
|
167
|
4 |
|
return $query; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Returns collection of tags for Kanban view. |
172
|
|
|
* |
173
|
|
|
* @param User $user |
174
|
|
|
* |
175
|
|
|
* @return mixed |
176
|
|
|
*/ |
177
|
|
|
public function getKanbanTagsForUser(User $user) |
178
|
|
|
{ |
179
|
|
|
$tags = $this->kanbanTags() |
|
|
|
|
180
|
|
|
->where(function (Eloquent\Builder $query) use ($user) { |
181
|
|
|
$query->where('role_limit', '<=', $user->role_id); |
182
|
|
|
$query->orWhere('role_limit', '=', null); |
183
|
|
|
}) |
184
|
|
|
->get(); |
185
|
|
|
|
186
|
|
|
return $tags; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Returns collection of issues grouped by tags. |
191
|
|
|
* |
192
|
|
|
* @param $tagIds |
193
|
|
|
* |
194
|
|
|
* @return mixed |
195
|
|
|
*/ |
196
|
|
|
public function issuesGroupByTags($tagIds) |
197
|
|
|
{ |
198
|
|
|
$issues = $this->issues() |
199
|
|
|
->with('user', 'tags') |
200
|
|
|
->where('status', '=', Project\Issue::STATUS_OPEN) |
201
|
|
|
->whereIn('projects_issues_tags.tag_id', $tagIds) |
202
|
|
|
->join('projects_issues_tags', 'issue_id', '=', 'id') |
203
|
|
|
->orderBy('id') |
204
|
|
|
->get() |
205
|
|
|
->groupBy(function (Project\Issue $issue) { |
206
|
|
|
return $issue->tags->last()->name; |
|
|
|
|
207
|
|
|
}); |
208
|
|
|
|
209
|
|
|
return $issues; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Returns users assigned to the project that can fix issues (with edit permission). |
214
|
|
|
* |
215
|
|
|
* @return Relations\BelongsToMany |
216
|
|
|
*/ |
217
|
8 |
|
public function usersCanFixIssue() |
218
|
|
|
{ |
219
|
8 |
|
return $this->users()->where('users.role_id', '>', 1); |
220
|
|
|
} |
221
|
|
|
} |
222
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.