Completed
Push — master ( f8a1a1...93e29b )
by Randy
02:37
created

EnsuranceTrait::either()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Dgame\Ensurance;
4
5
use Dgame\Ensurance\Exception\EnsuranceException;
6
use Throwable;
7
8
/**
9
 * Trait EnsuranceTrait
10
 * @package Dgame\Ensurance
11
 */
12
trait EnsuranceTrait
13
{
14
    /**
15
     * @var mixed
16
     */
17
    private $value;
18
    /**
19
     * @var bool
20
     */
21
    private $ensured = true;
22
    /**
23
     * @var
24
     */
25
    private $throwable;
26
27
    /**
28
     *
29
     */
30
    public function __destruct()
31
    {
32
        if ($this->hasThrowable()) {
33
            throw $this->throwable;
34
        }
35
    }
36
37
    /**
38
     * @param $value
39
     *
40
     * @return mixed
41
     */
42
    final public function then($value)
43
    {
44
        return $this->disregardThrowable()->isEnsured() ? $value : $this->value;
45
    }
46
47
    /**
48
     * @param $value
49
     *
50
     * @return mixed
51
     */
52
    final public function else($value)
0 ignored issues
show
Bug introduced by
Possible parse error: non-abstract method defined as abstract
Loading history...
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
53
    {
54
        return $this->disregardThrowable()->isEnsured() ? $this->value : $value;
55
    }
56
57
    /**
58
     * @param $value
59
     *
60
     * @return Either
61
     */
62
    final public function either($value): Either
63
    {
64
        return new Either($value, $this->disregardThrowable()->isEnsured());
65
    }
66
67
    /**
68
     * @param null $default
69
     *
70
     * @return null
71
     */
72
    final public function get($default = null)
73
    {
74
        return $this->value ?? $default;
75
    }
76
77
    /**
78
     * @param bool $condition
79
     *
80
     * @return self
81
     */
82
    final protected function ensure(bool $condition): self
83
    {
84
        $this->ensured = $condition;
85
86
        return $this;
87
    }
88
89
    /**
90
     * @return bool
91
     */
92
    final public function isEnsured(): bool
93
    {
94
        return $this->ensured;
95
    }
96
97
    /**
98
     * @return self
99
     */
100
    final public function disregardThrowable(): self
101
    {
102
        $this->throwable = null;
103
104
        return $this;
105
    }
106
107
    /**
108
     * @return Throwable
109
     */
110
    final public function releaseThrowable(): Throwable
111
    {
112
        try {
113
            return $this->throwable;
114
        } finally {
115
            $this->disregardThrowable();
0 ignored issues
show
Unused Code introduced by
$this->disregardThrowable(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
116
        }
117
    }
118
119
    /**
120
     * @param EnsuranceInterface $ensurance
121
     *
122
     * @return self
123
     */
124
    final public function transferEnsurance(EnsuranceInterface $ensurance): self
125
    {
126
        $this->value = $ensurance->get();
127
        $this->ensure($ensurance->isEnsured());
128
        if ($ensurance->hasThrowable()) {
129
            $this->setThrowable($ensurance->releaseThrowable());
130
        }
131
132
        return $this;
133
    }
134
135
    /**
136
     * @param string $message
137
     * @param mixed  ...$args
138
     *
139
     * @return self
140
     */
0 ignored issues
show
Documentation introduced by
Consider making the type for parameter $args a bit more specific; maybe use array.
Loading history...
141
    final public function orThrow(string $message, ...$args): self
142
    {
143
        if (!$this->isEnsured()) {
144
            $this->setThrowable(new EnsuranceException(format($message, ...$args), $this->throwable));
145
        }
146
147
        return $this;
148
    }
149
150
    /**
151
     * @return bool
152
     */
153
    final public function hasThrowable(): bool
154
    {
155
        return $this->throwable !== null;
156
    }
157
158
    /**
159
     * @param Throwable $throwable
160
     *
161
     * @return self
162
     */
163
    final public function setThrowable(Throwable $throwable): self
164
    {
165
        if (!$this->isEnsured()) {
166
            $this->throwable = $throwable;
167
        }
168
169
        return $this;
170
    }
171
172
    /**
173
     * @return Throwable
174
     */
175
    final public function getThrowable(): Throwable
176
    {
177
        return $this->throwable;
178
    }
179
}