Cutter   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 63
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 63
ccs 24
cts 24
cp 1
rs 10
wmc 9

2 Methods

Rating   Name   Duplication   Size   Complexity  
A cutInternal() 0 30 6
A cut() 0 14 3
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