Passed
Push — master ( 0cf9a8...478c1f )
by Anton
03:37
created

Reaction::changeRate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of Laravel Love.
5
 *
6
 * (c) Anton Komarev <[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
declare(strict_types=1);
13
14
namespace Cog\Laravel\Love\Reaction\Models;
15
16
use Cog\Contracts\Love\Reactant\Models\Reactant as ReactantContract;
17
use Cog\Contracts\Love\Reacter\Models\Reacter as ReacterContract;
18
use Cog\Contracts\Love\Reaction\Exceptions\RateOutOfRange;
19
use Cog\Contracts\Love\Reaction\Exceptions\RateInvalid;
20
use Cog\Contracts\Love\Reaction\Models\Reaction as ReactionContract;
21
use Cog\Contracts\Love\ReactionType\Models\ReactionType as ReactionTypeContract;
22
use Cog\Laravel\Love\Reactant\Models\Reactant;
23
use Cog\Laravel\Love\Reacter\Models\Reacter;
24
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
25
use Cog\Laravel\Love\Support\Database\Eloquent\Model;
26
use Illuminate\Database\Eloquent\Relations\BelongsTo;
27
28
final class Reaction extends Model implements
29
    ReactionContract
30
{
31
    public const RATE_DEFAULT = 1.0;
32
33
    public const RATE_MIN = 0.01;
34
35
    public const RATE_MAX = 99.99;
36
37
    protected $table = 'love_reactions';
38
39
    protected $attributes = [
40
        'rate' => self::RATE_DEFAULT,
41
    ];
42
43
    protected $fillable = [
44
        'reactant_id',
45
        'reaction_type_id',
46
        'rate',
47
    ];
48
49
    protected $casts = [
50
        'id' => 'string',
51
        'rate' => 'float',
52
    ];
53
54
    public function reactant(): BelongsTo
55
    {
56
        return $this->belongsTo(Reactant::class, 'reactant_id');
57
    }
58
59
    public function reacter(): BelongsTo
60
    {
61
        return $this->belongsTo(Reacter::class, 'reacter_id');
62
    }
63
64
    public function type(): BelongsTo
65
    {
66
        return $this->belongsTo(ReactionType::class, 'reaction_type_id');
67
    }
68
69
    public function getId(): string
70
    {
71
        return $this->getAttributeValue('id');
0 ignored issues
show
Bug Best Practice introduced by Anton Komarev
The expression return $this->getAttributeValue('id') could return the type boolean|null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
72
    }
73
74
    public function getReactant(): ReactantContract
75
    {
76
        return $this->getAttribute('reactant');
77
    }
78
79
    public function getReacter(): ReacterContract
80
    {
81
        return $this->getAttribute('reacter');
82
    }
83
84
    public function getType(): ReactionTypeContract
85
    {
86
        return $this->getAttribute('type');
87
    }
88
89
    public function getRate(): float
90
    {
91
        return $this->getAttributeValue('rate');
92
    }
93
94
    public function getWeight(): float
95
    {
96
        return $this->getType()->getMass() * $this->getRate();
97
    }
98
99
    public function setRateAttribute(
100
        ?float $rate
101
    ): void {
102
        if (!is_null($rate) && ($rate < self::RATE_MIN || $rate > self::RATE_MAX)) {
103
            throw RateOutOfRange::withValue($rate);
104
        }
105
106
        $this->attributes['rate'] = $rate;
107
    }
108
109
    public function isOfType(
110
        ReactionTypeContract $reactionType
111
    ): bool {
112
        return $this->getType()->isEqualTo($reactionType);
113
    }
114
115
    public function isNotOfType(
116
        ReactionTypeContract $reactionType
117
    ): bool {
118
        return $this->getType()->isNotEqualTo($reactionType);
119
    }
120
121
    public function isToReactant(
122
        ReactantContract $reactant
123
    ): bool {
124
        return $this->getReactant()->isEqualTo($reactant);
125
    }
126
127
    public function isNotToReactant(
128
        ReactantContract $reactant
129
    ): bool {
130
        return !$this->isToReactant($reactant);
131
    }
132
133
    public function isByReacter(
134
        ReacterContract $reacter
135
    ): bool {
136
        return $this->getReacter()->isEqualTo($reacter);
137
    }
138
139
    public function isNotByReacter(
140
        ReacterContract $reacter
141
    ): bool {
142
        return !$this->isByReacter($reacter);
143
    }
144
145
    public function changeRate(
146
        float $rate
147
    ): void {
148
        if ($this->getRate() === $rate) {
149
            throw RateInvalid::withSameValue($rate);
150
        }
151
152
        $this->setAttribute('rate', $rate);
153
        $this->save();
154
    }
155
}
156