Completed
Push — master ( 0fed18...2a299a )
by Sebastian
03:53
created

PasswordGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 0
c 0
b 0
f 0
dl 0
loc 2
ccs 0
cts 0
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * Linna Framework.
5
 *
6
 * @author Sebastian Rapetti <[email protected]>
7
 * @copyright (c) 2018, Sebastian Rapetti
8
 * @license http://opensource.org/licenses/MIT MIT License
9
 */
10
declare(strict_types=1);
11
12
namespace Linna\Authentication;
13
14
use InvalidArgumentException;
15
16
/**
17
 * Generate random password with random topology, this class use php7
18
 * random_int() function for generate random numbers.
19
 */
20
class PasswordGenerator
21
{
22
    /**
23
     * @var array Characters intervall
24
     */
25
    private $chars = [
26
        'ABCDEFGHIJKLMNOPQRSTUVWXYZ', //u 117
27
        'abcdefghijklmnopqrstuvwxyz', //l 108
28
        '0123456789', //d 100
29
        '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' //s 115
30
    ];
31
32
    /**
33
     * Class constructor.
34
     *
35
     * In this class constructor do nothing, is present only for compatibility with Container.
36
     *
37
     * <pre><code class="php">use Linna\Auth\PasswordGenerator;
38
     *
39
     * $passwordGenerator = new PasswordGenerator();
40
     * </code></pre>
41
     */
42
    public function __construct()
43
    {
44
    }
45
46
    /**
47
     * Generate a random password.
48 8
     *
49
     * <pre><code class="php">$random = $passwordGenerator->getFromRandom(20);
50 8
     *
51
     * //var_dump result
52 8
     * //r4Q,1J*tM7D_99q0u>61
53 8
     * var_dump($random);
54
     * </code></pre>
55 8
     *
56
     * @param int $length Desiderated password length.
57
     *
58 8
     * @return string Random password.
59
     */
60
    public function getFromRandom(int $length): string
61
    {
62
        $password = [];
63
64
        while ($length) {
65
            $password[] = $this->getRandomChar($this->chars[\random_int(0, 3)]);
66
67
            $length--;
68
        }
69
70
        return \implode($password);
71
    }
72
73
    /**
74
     * Return topology for given password.
75
     *
76 26
     * <pre><code class="php">$topology = $passwordGenerator->getTopology('r4Q,1J*tM7D_99q0u>61');
77
     *
78 26
     * //var_dump result
79 26
     * //ldusdusludusddldlsdd
80
     * var_dump($topology);
81 26
     * </code></pre>
82 26
     *
83
     * @param string $password Password for which get topology.
84
     *
85 25
     * @return string Topology for the argument passed password.
86
     */
87
    public function getTopology(string $password): string
88
    {
89
        $array = \str_split($password);
90
        $topology = [];
91
92
        foreach ($array as $char) {
93
            $topology[] = $this->getTopologyGroup($char);
94
        }
95
96
        return \implode($topology);
97 26
    }
98
99 26
    /**
100
     * Return topology group for the given char.
101 26
     *
102 25
     * @param string $char
103
     *
104
     * @return string
105 26
     *
106 25
     * @throws InvalidArgumentException If char provided isn't inside any group
107
     */
108
    private function getTopologyGroup(string $char): string
109 26
    {
110 25
        $groups = $this->chars;
111
112
        if (\strpos($groups[0], $char) !== false) {
113 26
            return 'u';
114 25
        }
115
116
        if (\strpos($groups[1], $char) !== false) {
117 1
            return 'l';
118
        }
119
120
        if (\strpos($groups[2], $char) !== false) {
121
            return 'd';
122
        }
123
124
        if (\strpos($groups[3], $char) !== false) {
125
            return 's';
126
        }
127
128
        throw new InvalidArgumentException('Out of group character provided.');
129
    }
130
131
    /**
132
     * Generate a random password corresponding at the given topology.
133
     *
134
     * <pre><code class="php">$random = $passwordGenerator->getFromTopology('ldusdusludusddldlsdd');
135
     *
136
     * //var_dump result
137
     * //r4Q,1J*tM7D_99q0u>61
138 16
     * var_dump($random);
139
     * </code></pre>
140 16
     *
141 16
     * @param string $topology Topology for generate password.
142 16
     *
143
     * @return string Random password corresponding the given topology.
144 16
     *
145 16
     * @throws InvalidArgumentException If invalid pattern is provided.
146
     */
147 16
    public function getFromTopology(string $topology): string
148 13
    {
149
        $array = \str_split(\strtolower($topology));
150 13
        $groups = [117 => 0, 108 => 1, 100 => 2, 115 => 3];
151
        $password = [];
152
153 6
        foreach ($array as $char) {
154
            $int = \ord($char);
155
156 10
            if (isset($groups[$int])) {
157
                $password[] = $this->getRandomChar($this->chars[$groups[$int]]);
158
159
                continue;
160
            }
161
162
            throw new InvalidArgumentException('Invalid pattern provided, accepted only u, l, d and s.');
163
        }
164
165
        return \implode($password);
166 21
    }
167
168 21
    /**
169 21
     * Get random char between.
170
     *
171 21
     * @param string $interval
172
     *
173
     * @return string
174
     */
175
    private function getRandomChar(string $interval): string
176
    {
177
        $size = \strlen($interval) - 1;
178
        $int = \random_int(0, $size);
179
180
        return $interval[$int];
181
    }
182
}
183