Cutter::cutInternal()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 16
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 30
ccs 17
cts 17
cp 1
crap 6
rs 9.1111
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\PasswordPolice\CharTree;
6
7
use InvalidArgumentException;
8
use Stadly\PasswordPolice\CharTree;
9
10
final class Cutter
11
{
12
    /**
13
     * @var array<array<array<string|CharTree>>> Memoization of cut character trees.
14
     */
15
    private static $memoization = [];
16
17
    /**
18
     * @param CharTree $charTree Character tree to cut.
19
     * @param int $position Number of characters before cut.
20
     * @return array<array<string|CharTree>> Cut variants of the character tree.
21
     */
22 14
    public function cut(CharTree $charTree, int $position): array
23
    {
24 14
        if ($position < 0) {
25 4
            throw new InvalidArgumentException('Position must be non-negative.');
26
        }
27
28
        // When PHP 7.1 is no longer supported, change to using spl_object_id.
29 10
        $hash = spl_object_hash($charTree) . ';' . $position;
30
31 10
        if (!isset(self::$memoization[$hash])) {
32 10
            self::$memoization[$hash] = $this->cutInternal($charTree, $position);
33
        }
34
35 10
        return self::$memoization[$hash];
36
    }
37
38
    /**
39
     * @param CharTree $charTree Character tree to cut.
40
     * @param int $position Number of characters before cut.
41
     * @return array<array<string|CharTree>> Cut variants of the character tree. Memoization is not used.
42
     */
43 10
    private function cutInternal(CharTree $charTree, int $position): array
44
    {
45 10
        $root = $charTree->getRoot();
46
47 10
        if ($root === null) {
48 3
            return [];
49
        }
50
51 8
        $rootLength = mb_strlen($root);
52 8
        $branchPosition = $position - $rootLength;
53
54 8
        if ($branchPosition < 0) {
55 1
            return [['', $charTree]];
56
        }
57
58 7
        if ($branchPosition === 0) {
59 5
            return [[$root, CharTree::fromArray($charTree->getBranches())]];
60
        }
61
62 5
        $cutCharTrees = [];
63 5
        foreach ($charTree->getBranches() as $branch) {
64 4
            foreach ($this->cut($branch, $branchPosition) as [$branchRoot, $branchTree]) {
65 3
                assert(is_string($branchRoot));
66 3
                assert(is_object($branchTree));
67
68 4
                $cutCharTrees[] = [$root . $branchRoot, $branchTree];
69
            }
70
        }
71
72 5
        return $cutCharTrees;
73
    }
74
}
75