Completed
Branch master (b7c8d8)
by
unknown
28:56 queued 12:06
created

BIP32Path::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Blocktrail\SDK\Bitcoin;
4
5
/**
6
 * Class BIP32Path
7
 *
8
 * BIP32 path, does not mutate itself but returns new instance everytime
9
 *
10
 * @package Blocktrail\SDK
11
 */
12
class BIP32Path implements \ArrayAccess {
13
    protected $path;
14
15 84
    public function __construct($path) {
16 84
        $this->path = is_array($path) ? $path : explode("/", $path);
17
18 84
        if (strtolower($this->path[0]) != "m") {
19
            throw new \InvalidArgumentException("BIP32Path can only be used for absolute paths");
20
        }
21 84
    }
22
23
    /**
24
     * @return int
25
     */
26 1
    public function depth() {
27 1
        return count($this->path);
28
    }
29
30 1
    public function insert($insert, $offset) {
31 1
        $path = $this->path;
32
33 1
        array_splice($path, $offset+1, 0, [$insert]);
34
35 1
        return new static($path);
36
    }
37
38
    /**
39
     * increase the last level of the path by 1 and return the new path
40
     *
41
     * @return BIP32Path
42
     */
43 1
    public function next() {
44 1
        $path = $this->path;
45
46 1
        $last = array_pop($path);
47
48 1
        if ($hardened = (strpos($last, "'") !== false)) {
49
            $last = str_replace("'", "", $last);
50
        }
51
52 1
        $last = (int)$last;
53 1
        $last += 1;
54
55 1
        if ($hardened) {
56
            $last .= "'";
57
        }
58
59 1
        $path[] = $last;
60
61 1
        return new static($path);
62
    }
63
64
    /**
65
     * pop off one level of the path and return the new path
66
     *
67
     * @return BIP32Path
68
     */
69 29
    public function parent() {
70 29
        $path = $this->path;
71
72 29
        array_pop($path);
73
74 29
        if (empty($path)) {
75
            throw new \RuntimeException("Can't get parent of root path");
76
        }
77
78 29
        return new static($path);
79
    }
80
81
    /**
82
     * get child $child of the current path and return the new path
83
     *
84
     * @param $child
85
     * @return BIP32Path
86
     */
87 1
    public function child($child) {
88 1
        $path = $this->path;
89
90 1
        $path[] = $child;
91
92 1
        return new static($path);
93
    }
94
95
    /**
96
     * pop off one level of the path and add $last and return the new path
97
     *
98
     * @param $last
99
     * @return BIP32Path
100
     */
101 12
    public function last($last) {
102 12
        $path = $this->path;
103
104 12
        array_pop($path);
105 12
        $path[] = $last;
106
107 12
        return new static($path);
108
    }
109
110
    /**
111
     * harden the last level of the path and return the new path
112
     *
113
     * @return BIP32Path
114
     */
115 1
    public function hardened() {
116 1
        $path = $this->path;
117
118 1
        $last = array_pop($path);
119
120 1
        if (strpos($last, "'") !== false) {
121
            return $this;
122
        }
123
124 1
        $last .= "'";
125
126 1
        $path[] = $last;
127
128 1
        return new static($path);
129
    }
130
131
    /**
132
     * unharden the last level of the path and return the new path
133
     *
134
     * @return BIP32Path
135
     */
136 1
    public function unhardenedLast() {
137 1
        $path = $this->path;
138
139 1
        $last = array_pop($path);
140
141 1
        $last = str_replace("'", "", $last);
142
143 1
        $path[] = $last;
144
145 1
        return new static($path);
146
    }
147
148
    /**
149
     * unharden all levels of the path and return the new path
150
     *
151
     * @return BIP32Path
152
     */
153 32
    public function unhardenedPath() {
154 32
        $path = $this->path;
155
156 32
        foreach ($path as $i => $level) {
157 32
            $path[$i] = str_replace("'", "", $level);
158
        }
159
160 32
        return new static($path);
161
    }
162
163
    /**
164
     * change the path to be for the public key (starting with M/) and return the new path
165
     *
166
     * @return BIP32Path
167
     */
168 38
    public function publicPath() {
169 38
        $path = $this->path;
170
171 38
        if ($path[0] === "M") {
172 31
            return new static($path);
173
        } else {
174 21
            $path[0] = "M";
175
176 21
            return new static($path);
177
        }
178
    }
179
180
    /**
181
     * change the path to be for the private key (starting with m/) and return the new path
182
     *
183
     * @return BIP32Path
184
     */
185 27
    public function privatePath() {
186 27
        $path = $this->path;
187
188 27
        if ($path[0] === "m") {
189 1
            return new static($path);
190
        } else {
191 26
            $path[0] = "m";
192
193 26
            return new static($path);
194
        }
195
    }
196
197
    /**
198
     * get the string representation of the path
199
     *
200
     * @return string
201
     */
202 41
    public function getPath() {
203 41
        return implode("/", $this->path);
204
    }
205
206
    /**
207
     * get the last part of the path
208
     *
209
     * @return string
210
     */
211
    public function getLast() {
212
        return $this->path[count($this->path)-1];
213
    }
214
215
    /**
216
     * check if the last level of the path is hardened
217
     *
218
     * @return bool
219
     */
220 29
    public function isHardened() {
221 29
        $path = $this->path;
222
223 29
        $last = array_pop($path);
224
225 29
        return strpos($last, "'") !== false;
226
    }
227
228
    /**
229
     * check if the last level of the path is hardened
230
     *
231
     * @return bool
232
     */
233 2
    public function isPublicPath() {
234 2
        $path = $this->path;
235
236 2
        return $path[0] == "M";
237
    }
238
239
    /**
240
     * check if this path is parent path of the provided path
241
     *
242
     * @param string|BIP32Path $path
243
     * @return bool
244
     */
245 1
    public function isParentOf($path) {
246 1
        $path = BIP32Path::path($path);
0 ignored issues
show
Coding Style introduced by
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
247
248 1
        return strlen((string)$path) > strlen((string)$this) && strpos((string)$path, (string)$this) === 0;
249
    }
250
251
    /**
252
     * static method to initialize class
253
     *
254
     * @param $path
255
     * @return BIP32Path
256
     */
257 84
    public static function path($path) {
258 84
        if ($path instanceof static) {
259 39
            return $path;
260
        }
261
262 84
        return new static($path);
263
    }
264
265 28
    public function getKeyIndex() {
266 28
        return str_replace("'", "", $this->path[1]);
267
    }
268
269
    /**
270
     * count the levels in the path (including master)
271
     *
272
     * @return int
273
     */
274 28
    public function count() {
275 28
        return count($this->path);
276
    }
277
278
279
    public function offsetExists($offset) {
280
        return isset($this->path[$offset]);
281
    }
282
283 56
    public function offsetGet($offset) {
284 56
        return isset($this->path[$offset]) ? $this->path[$offset] : null;
285
    }
286
287
    public function offsetSet($offset, $value) {
288
        throw new \Exception("Not implemented");
289
    }
290
291
    public function offsetUnset($offset) {
292
        throw new \Exception("Not implemented");
293
    }
294
295
    /**
296
     * @return string
297
     */
298 41
    public function __toString() {
299 41
        return $this->getPath();
300
    }
301
}
302