Completed
Push — master ( 6f364e...f38e11 )
by Magnar Ovedal
10:44 queued 07:28
created

Truncator::format()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 4
nop 2
dl 0
loc 21
ccs 12
cts 12
cp 1
crap 4
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\PasswordPolice\Formatter;
6
7
use InvalidArgumentException;
8
use Stadly\PasswordPolice\CharTree;
9
use Stadly\PasswordPolice\Formatter;
10
11
final class Truncator implements Formatter
12
{
13
    use Chaining;
14
15
    /**
16
     * @var int Maximum string length.
17
     */
18
    private $length;
19
20
    /**
21
     * @var CharTree[] Memoization of formatted character trees.
22
     */
23
    private static $memoization = [];
24
25
    /**
26
     * @param int $length Maximum string length.
27
     */
28 9
    public function __construct(int $length)
29
    {
30 9
        if ($length < 0) {
31 1
            throw new InvalidArgumentException('Length must be non-negative.');
32
        }
33
34 8
        $this->length = $length;
35 8
    }
36
37
    /**
38
     * @param CharTree $charTree Character tree to format.
39
     * @return CharTree Truncated variant of the character tree.
40
     */
41 8
    protected function applyCurrent(CharTree $charTree): CharTree
42
    {
43 8
        return $this->applyInternal($charTree, $this->length);
44
    }
45
46
    /**
47
     * @param CharTree $charTree Character tree to format.
48
     * @param int $length Maximum string length.
49
     * @return CharTree Truncated variant of the character tree.
50
     */
51 8
    private function applyInternal(CharTree $charTree, int $length): CharTree
52
    {
53
        // When PHP 7.1 is no longer supported, change to using spl_object_id.
54 8
        $hash = spl_object_hash($charTree).';'.$length;
55
56 8
        if (!isset(self::$memoization[$hash])) {
57 8
            self::$memoization[$hash] = $this->format($charTree, $length);
58
        }
59
60 8
        return self::$memoization[$hash];
61
    }
62
63
    /**
64
     * @param CharTree $charTree Character tree to format.
65
     * @param int $length Maximum string length.
66
     * @return CharTree Truncated variant of the character tree. Memoization is not used.
67
     */
68 8
    private function format(CharTree $charTree, int $length): CharTree
69
    {
70 8
        $root = $charTree->getRoot();
71
72 8
        if ($root === null) {
73 4
            return $charTree;
74
        }
75
76 6
        $rootLength = mb_strlen($root);
77 6
        $branchLength = $length-$rootLength;
78
79 6
        if ($branchLength < 0) {
80 3
            return CharTree::fromString('');
81
        }
82
83 6
        $truncatedBranches = [];
84 6
        foreach ($charTree->getBranches() as $branch) {
85 6
            $truncatedBranches[] = $this->applyInternal($branch, $branchLength);
86
        }
87
88 6
        return CharTree::fromString($root, $truncatedBranches);
89
    }
90
}
91