Completed
Push — master ( 929618...ebf749 )
by Magnar Ovedal
35:59 queued 19:38
created

Cutter::cut()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 2
dl 0
loc 14
rs 10
c 0
b 0
f 0
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 (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 (string|CharTree)[][] Cut variants of the character tree.
21
     */
22
    public function cut(CharTree $charTree, int $position): array
23
    {
24
        if ($position < 0) {
25
            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
        $hash = spl_object_hash($charTree).';'.$position;
30
31
        if (!isset(self::$memoization[$hash])) {
32
            self::$memoization[$hash] = $this->cutInternal($charTree, $position);
33
        }
34
35
        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 (string|CharTree)[][] Cut variants of the character tree. Memoization is not used.
42
     */
43
    private function cutInternal(CharTree $charTree, int $position): array
44
    {
45
        $root = $charTree->getRoot();
46
47
        if ($root === null) {
48
            return [];
49
        }
50
51
        $rootLength = mb_strlen($root);
52
        $branchPosition = $position-$rootLength;
53
54
        if ($branchPosition < 0) {
55
            return [['', $charTree]];
56
        }
57
58
        if ($branchPosition === 0) {
59
            return [[$root, CharTree::fromArray($charTree->getBranches())]];
60
        }
61
62
        $cutCharTrees = [];
63
        foreach ($charTree->getBranches() as $branch) {
64
            foreach ($this->cut($branch, $branchPosition) as [$branchRoot, $branchTree]) {
65
                assert(is_string($branchRoot));
66
                assert(is_object($branchTree));
67
68
                $cutCharTrees[] = [$root.$branchRoot, $branchTree];
69
            }
70
        }
71
72
        return $cutCharTrees;
73
    }
74
}
75