Completed
Push — develop ( 31039e...ea14db )
by Mohamed
05:36
created

Project::can()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 13
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 13
loc 13
ccs 0
cts 0
cp 0
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
crap 6
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;
13
14
use Illuminate\Database\Eloquent\Collection;
15
use Illuminate\Database\Eloquent\Model;
16
use Tinyissue\Contracts\Model\AccessControl;
17
use URL;
18
19
/**
20
 * Project is model class for projects.
21
 *
22
 * @author Mohamed Alsharaf <[email protected]>
23
 *
24
 * @property int $id
25
 * @property string $name
26
 * @property int $status
27
 * @property int $default_assignee
28
 * @property int $private
29
 * @property int $openIssuesCount
30
 * @property int $closedIssuesCount
31
 * @property int $closedIssuesCount
32
 * @property Collection $issues
33
 * @property Collection $issuesByUser
34
 * @property Collection $users
35
 * @property Collection $projectUsers
36
 * @property Collection $activities
37
 * @property Collection $notes
38
 * @property Collection $kanbanTags
39
 */
40
class Project extends Model implements AccessControl
41
{
42
    use Traits\CountAttributeTrait,
43
        Traits\Project\CountTrait,
44
        Traits\Project\FilterTrait,
45
        Traits\Project\SortTrait,
46
        Traits\Project\RelationTrait,
47
        Traits\Project\CrudTrait,
48
        Traits\Project\QueryTrait;
49
50
    /**
51
     * Project private & user role can see their own issues only.
52
     *
53
     * @var int
54
     */
55
    const INTERNAL_YES = 2;
56
57
    /**
58
     * Project not public to view and create issue.
59
     *
60
     * @var int
61
     */
62
    const PRIVATE_YES = 1;
63
64
    /**
65
     * Project public to view and create issue.
66
     *
67
     * @var int
68
     */
69
    const PRIVATE_NO = 0;
70
71
    /**
72
     * All projects.
73
     *
74
     * @var int
75
     */
76
    const PRIVATE_ALL = -1;
77
78
    /**
79
     * Project status Open.
80
     *
81
     * @var int
82
     */
83
    const STATUS_OPEN = 1;
84
85
    /**
86
     * Project status Archived.
87
     *
88
     * @var int
89
     */
90
    const STATUS_ARCHIVED = 0;
91
92
    /**
93
     * Timestamp enabled.
94
     *
95
     * @var bool
96
     */
97
    public $timestamps = true;
98
99
    /**
100
     * Name of database table.
101
     *
102
     * @var string
103
     */
104
    protected $table = 'projects';
105
106
    /**
107
     * List of allowed columns to be used in $this->fill().
108
     *
109
     * @var array
110
     */
111
    protected $fillable = ['name', 'default_assignee', 'status', 'private'];
112
113
    /**
114
     * List of HTML classes for each status.
115
     *
116
     * @var array
117
     */
118
    protected $attrClassNames = [
119
        self::PRIVATE_NO   => 'note',
120
        self::PRIVATE_YES  => 'info',
121
        self::INTERNAL_YES => 'primary',
122
    ];
123
124
    /**
125
     * List of statuses names.
126
     *
127
     * @var array
128
     */
129
    protected $statusesNames = [
130
        self::PRIVATE_NO   => 'public',
131
        self::PRIVATE_YES  => 'private',
132
        self::INTERNAL_YES => 'internal',
133
    ];
134
135
    /**
136
     * Generate a URL for the active project.
137
     *
138
     * @param string $url
139
     *
140
     * @return string
141
     */
142
    public function to($url = '')
143 45
    {
144
        return URL::to('project/' . $this->id . (($url) ? '/' . $url : ''));
145 45
    }
146
147
    /**
148
     * Returns the aggregate value of number of open issues in the project.
149
     *
150
     * @return int
151
     */
152
    public function getOpenIssuesCountAttribute()
153 5
    {
154
        return $this->getCountAttribute('openIssuesCount');
155 5
    }
156
157
    /**
158
     * Returns the aggregate value of number of closed issues in the project.
159
     *
160
     * @return int
161
     */
162
    public function getClosedIssuesCountAttribute()
163 1
    {
164
        return $this->getCountAttribute('closedIssuesCount');
165 1
    }
166
167
    /**
168
     * Set default assignee attribute.
169
     *
170
     * @param int $value
171
     *
172
     * @return $this
173
     */
174
    public function setDefaultAssigneeAttribute($value)
175 54
    {
176
        if (!empty($value)) {
177 54
            $this->attributes['default_assignee'] = (int) $value;
178 35
        }
179
180
        return $this;
181 54
    }
182
183
    /**
184
     * Returns the aggregate value of number of issues in the project.
185
     *
186
     * @return int
187
     */
188
    public function getIssuesCountAttribute()
189
    {
190
        return $this->getCountAttribute('issuesCount');
191
    }
192
193
    /**
194
     * Get total issues total quote time.
195
     *
196
     * @return int
197
     */
198
    public function getTotalQuote()
199 3
    {
200
        $total = 0;
201 3
        foreach ($this->issues as $issue) {
202 3
            $total += $issue->time_quote;
203 3
        }
204
205
        return $total;
206 3
    }
207
208
    /**
209
     * Calculate the progress (open & closed issues).
210
     *
211
     * @return float|int
212
     */
213
    public function getProgress()
214 1
    {
215
        $total    = $this->openIssuesCount + $this->closedIssuesCount;
216 1
        $progress = 100;
217 1
        if ($total > 0) {
218 1
            $progress = (float) ($this->closedIssuesCount / $total) * 100;
219 1
        }
220
        $progressInt = (int) $progress;
221 1
        if ($progressInt > 0) {
222 1
            $progress = number_format($progress, 2);
223 1
            $fraction = $progress - $progressInt;
224 1
            if ($fraction === 0.0) {
225 1
                $progress = $progressInt;
226 1
            }
227
        }
228
229
        return $progress;
230 1
    }
231
232
    /**
233
     * Whether or not a user is member of the project.
234
     *
235
     * @param int $userId
236
     *
237
     * @return bool
238
     */
239
    public function isMember($userId)
240 10
    {
241
        return $this->user($userId)->count() > 0;
242 10
    }
243
244
    /**
245
     * Whether or not the project is private.
246
     *
247
     * @return bool
248
     */
249
    public function isPrivate()
250 2
    {
251
        return (int) $this->private === self::PRIVATE_YES;
252 2
    }
253
254
    /**
255
     * Whether or not the project is public.
256
     *
257
     * @return bool
258
     */
259
    public function isPublic()
260 34
    {
261
        return (int) $this->private === self::PRIVATE_NO;
262 34
    }
263
264
    /**
265
     * Whether or not the project is private internal.
266
     *
267
     * @return bool
268
     */
269
    public function isPrivateInternal()
270 29
    {
271
        return (int) $this->private === self::INTERNAL_YES;
272 29
    }
273
274
    /**
275
     * Returns project status as string name.
276
     *
277
     * @return string
278
     */
279
    public function getStatusAsName()
280 2
    {
281
        if (array_key_exists((int) $this->private, $this->statusesNames)) {
282 2
            return $this->statusesNames[(int) $this->private];
283 2
        }
284
285
        return '';
286
    }
287
288
    /**
289
     * Returns the class name to be used for project status.
290
     *
291
     * @return string
292
     */
293
    public function getStatusClass()
294 2
    {
295
        if (array_key_exists((int) $this->private, $this->attrClassNames)) {
296 2
            return $this->attrClassNames[(int) $this->private];
297 2
        }
298
299
        return '';
300
    }
301
302
    /**
303
     * Whether or not a user can access the project.
304
     *
305
     * @param User $user
306
     *
307
     * @return bool
308
     */
309
    public function canView(User $user)
310 3
    {
311
        // Is member of the project
312
        if (
313
            ($this->isPublic() && app('tinyissue.settings')->isPublicProjectsEnabled()) ||
314 3
            $this->isMember($user->id)
315 3
        ) {
316
            return true;
317 1
        }
318
319
        return false;
320 3
    }
321
322
    /**
323
     * Whether a user can edit the project.
324
     *
325
     * @param User $user
326
     *
327
     * @return bool
328
     */
329
    public function canEdit(User $user)
330
    {
331
        return $user->permission(Permission::PERM_PROJECT_MODIFY) || $user->permission(Permission::PERM_PROJECT_ALL);
332
    }
333
334
    /**
335
     * @param string $permission
336
     * @param User   $user
337
     *
338
     * @return bool
339
     */
340 View Code Duplication
    public function can($permission, User $user)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
341
    {
342
        $editPermissions = [
343
            Permission::PERM_PROJECT_CREATE,
344
            Permission::PERM_PROJECT_MODIFY,
345
        ];
346
347
        if (in_array($permission, $editPermissions)) {
348
            return $this->canEdit($user);
349
        }
350
351
        return $this->canView($user);
352
    }
353
}
354