Completed
Push — master ( d3922b...937be3 )
by Christopher
01:16
created

Project::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Chriscreates\Projects\Models;
4
5
use BadMethodCallException;
6
use Carbon\Carbon;
7
use Chriscreates\Projects\Traits\HasStatus;
8
use Chriscreates\Projects\Traits\HasUsers;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Eloquent\Relations\BelongsTo;
11
use Illuminate\Database\Eloquent\Relations\morphMany;
12
use Illuminate\Database\Eloquent\Relations\MorphToMany;
13
14
class Project extends Model
15
{
16
    use HasUsers, HasStatus;
17
18
    protected $table = 'projects';
19
20
    public $primaryKey = 'id';
21
22
    public $guarded = ['id'];
23
24
    public $timestamps = true;
25
26
    protected $dates = [
27
        'started_at',
28
        'delivered_at',
29
        'expected_at',
30
    ];
31
32
    protected $casts = [
33
        'visible' => 'bool',
34
    ];
35
36
    public function __construct(array $attributes = [])
37
    {
38
        parent::__construct($attributes);
39
    }
40
41
    public function author() : BelongsTo
42
    {
43
        return $this->belongsTo(get_class(user_model()), 'author_id');
44
    }
45
46
    public function owner() : BelongsTo
47
    {
48
        return $this->belongsTo(get_class(user_model()), 'owner_id');
49
    }
50
51
    public function status() : BelongsTo
52
    {
53
        return $this->belongsTo(Status::class);
54
    }
55
56
    public function tasks() : MorphToMany
57
    {
58
        return $this->morphedByMany(Task::class, 'projectable');
59
    }
60
61
    public function comments() : MorphMany
62
    {
63
        return $this->morphMany(Comment::class, 'commentable');
64
    }
65
66
    public function isVisible() : bool
67
    {
68
        return $this->attributes['visible'] == true;
69
    }
70
71
    public function isNotVisible() : bool
72
    {
73
        return $this->attributes['visible'] == false;
74
    }
75
76
    public function dueIn(string $format = 'days') : int
77
    {
78
        $method = 'diffIn'.ucfirst($format);
79
80
        if ( ! $this->hasDateTarget()) {
81
            return 0;
82
        }
83
84
        if ( ! method_exists(Carbon::class, $method)) {
85
            throw new BadMethodCallException(sprintf(
86
                'Method %s::%s does not exist.',
87
                Carbon::class,
88
                $method
89
            ));
90
        }
91
92
        return $this->started_at->$method($this->expected_at);
93
    }
94
95
    public function assignTask(Task $task) : void
96
    {
97
        $this->tasks()->save($task);
98
99
        $this->refresh();
100
    }
101
102
    public function removeTask(Task $task) : void
103
    {
104
        $this->tasks()->detach($task);
105
106
        $this->refresh();
107
    }
108
109
    public function hasTask(Task $task) : bool
110
    {
111
        $this->refresh();
112
113
        return $this->tasks->contains($task->id);
114
    }
115
116
    /**
117
     * Has the task got an expected target.
118
     *
119
     * @return bool
120
     */
121
    public function hasDateTarget() : bool
122
    {
123
        return $this->attributes['started_at'] || $this->attributes['expected_at'];
124
    }
125
126
    /**
127
     * Is the task still in process.
128
     *
129
     * @return bool
130
     */
131
    public function isInProcess() : bool
132
    {
133
        return is_null($this->attributes['delivered_at']);
134
    }
135
136
    /**
137
     * Is the task not due yet.
138
     *
139
     * @return bool
140
     */
141
    public function notDueYet() : bool
142
    {
143
        return $this->expected_at->greaterThan(now());
144
    }
145
146
    /**
147
     * Is the task complete.
148
     *
149
     * @return bool
150
     */
151
    public function completed() : bool
152
    {
153
        if ( ! $this->hasDateTarget() || $this->isInProcess()) {
154
            return false;
155
        }
156
157
        return ($this->completedOnSchedule()
158
        || $this->completedAfterSchedule())
159
        && $this->completedAllTasks();
160
    }
161
162
    /**
163
     * Was the task completed after the given deadline.
164
     *
165
     * @return bool
166
     */
167
    public function completedAfterSchedule() : bool
168
    {
169
        return $this->delivered_at->greaterThan($this->expected_at);
170
    }
171
172
    /**
173
     * Was the task completed before the given deadline.
174
     *
175
     * @return bool
176
     */
177
    public function completedBeforeSchedule() : bool
178
    {
179
        return $this->delivered_at->lessThan($this->expected_at);
180
    }
181
182
    /**
183
     * Was the task completed before or on the given deadline.
184
     *
185
     * @return bool
186
     */
187
    public function completedOnSchedule() : bool
188
    {
189
        return $this->delivered_at->lessThanOrEqualTo($this->expected_at);
190
    }
191
192
    /**
193
     * Is the task overdue.
194
     *
195
     * @return bool
196
     */
197
    public function isOverdue() : bool
198
    {
199
        return $this->isInProcess() && ! $this->notDueYet();
200
    }
201
202
    /**
203
     * Have all tasks been completed.
204
     *
205
     * @return bool
206
     */
207
    public function completedAllTasks() : bool
208
    {
209
        $this->load('tasks');
210
211
        if ($this->tasks->isEmpty()) {
212
            return true;
213
        }
214
215
        return $this->tasks->count() === $this->tasks->sum->completed();
216
    }
217
}
218