Passed
Push — master ( 56ac53...50cf31 )
by Carlos C
03:36
created

BaseConverter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
namespace CfdiUtils\Internals;
3
4
/**
5
 * Converts any string of any base to any other base without
6
 * PHP native method base_convert's double and float limitations.
7
 *
8
 * @see https://php.net/base_convert
9
 * Original author: https://github.com/credomane/php_baseconvert
10
 *
11
 * NOTE: Changes will not be considering a bracking compatibility change since this utility is for internal usage only
12
 * @internal
13
 */
14
class BaseConverter
15
{
16
    /** @var BaseConverterSequence */
17
    private $sequence;
18
19 17
    public function __construct(BaseConverterSequence $sequence)
20
    {
21 17
        $this->sequence = $sequence;
22 17
    }
23
24 15
    public static function createBase36(): self
25
    {
26 15
        return new self(new BaseConverterSequence('0123456789abcdefghijklmnopqrstuvwxyz'));
27
    }
28
29 9
    public function sequence(): BaseConverterSequence
30
    {
31 9
        return $this->sequence;
32
    }
33
34 14
    public function maximumBase(): int
35
    {
36 14
        return $this->sequence->length();
37
    }
38
39 17
    public function convert(string $input, int $frombase, int $tobase): string
40
    {
41 17
        if ($frombase < 2 || $frombase > $this->maximumBase()) {
42 4
            throw new \UnexpectedValueException('Invalid from base');
43
        }
44 13
        if ($tobase < 2 || $tobase > $this->maximumBase()) {
45 4
            throw new \UnexpectedValueException('Invalid to base');
46
        }
47
48 9
        $originalSequence = $this->sequence()->value();
49 9
        if ('' === $input) {
50 1
            $input = $originalSequence{0}; // use zero as input
51
        }
52 9
        $chars = substr($originalSequence, 0, $frombase);
53 9
        if (! boolval(preg_match("/^[$chars]+$/", $input))) {
54 1
            throw new \UnexpectedValueException('The number to convert contains invalid characters');
55
        }
56
57 8
        $length = strlen($input);
58 8
        $values = [];
59 8
        for ($i = 0; $i < $length; $i++) {
60 8
            $values[] = intval(stripos($originalSequence, $input{$i}));
61
        }
62
63 8
        $result = '';
64
        do {
65 8
            $divide = 0;
66 8
            $newlen = 0;
67 8
            for ($i = 0; $i < $length; $i++) {
68 8
                $divide = $divide * $frombase + $values[$i];
69 8
                if ($divide >= $tobase) {
70 5
                    $values[$newlen] = intval($divide / $tobase);
71 5
                    $divide = $divide % $tobase;
72 5
                    $newlen = $newlen + 1;
73 8
                } elseif ($newlen > 0) {
74 4
                    $values[$newlen] = 0;
75 4
                    $newlen = $newlen + 1;
76
                }
77
            }
78 8
            $length = $newlen;
79 8
            $result = $originalSequence{$divide} . $result;
80 8
        } while ($newlen > 0);
81
82 8
        return $result;
83
    }
84
}
85