Completed
Branch develop-3.0 (4fe777)
by Mohamed
11:06
created

Project::getClosedIssuesCountAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
312
        ) {
313
            return true;
314
        }
315
316
        return false;
317
    }
318
319
    /**
320
     * Whether a user can edit the project.
321
     *
322
     * @param UserInterface $user
323
     *
324
     * @return bool
325
     */
326
    public function canEdit(UserInterface $user)
327
    {
328
        return $user->permission(Permission::PERM_PROJECT_MODIFY) || $user->permission(Permission::PERM_PROJECT_ALL);
329
    }
330
331
    /**
332
     * @param string        $permission
333
     * @param UserInterface $user
334
     *
335
     * @return bool
336
     */
337 View Code Duplication
    public function can($permission, UserInterface $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...
338
    {
339
        $editPermissions = [
340
            Permission::PERM_PROJECT_CREATE,
341
            Permission::PERM_PROJECT_MODIFY,
342
        ];
343
344
        if (in_array($permission, $editPermissions)) {
345
            return $this->canEdit($user);
346
        }
347
348
        return $this->canView($user);
349
    }
350
351
    public function getPreferredMessageIdForUser($userId)
352
    {
353
        return $this->projectUsers()
354
            ->where('user_id', '=', $userId)
355
            ->first()
356
            ->message_id;
357
    }
358
}
359