Generator   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 2
dl 0
loc 126
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 20 8
A __get() 0 8 3
A __set() 0 6 3
B generate() 0 28 6
1
<?php
2
3
namespace PassGenerator;
4
5
/**
6
 * Generate random password string according to specific configurations.
7
 * It can customize password length and minimum and maximum sizes.
8
 * The allowed configuration options are:
9
 *  - upperCase: all alphabet upper letters [A-Z]
10
 *  - lowerCase: all alphabet lower letters [a-z]
11
 *  - digits: all numbers [0-9]
12
 *  - special: special symbols ~,!,@,#,...
13
 *  - brackets: all kind of brackets (,),{,},[,]
14
 *  - minus: minus sign -
15
 *  - underline: underline sign _
16
 *  - space: space character
17
 *  - length: password string size
18
 * 
19
 * @property string $password the generated password
20
 * @property boolean $upperCase
21
 * @property boolean $lowerCase
22
 * @property boolean $digits
23
 * @property boolean $special
24
 * @property boolean $brackets
25
 * @property boolean $minus
26
 * @property boolean $underline
27
 * @property boolean $space
28
 * @property integer $length
29
 * 
30
 * @author Lachezar Mihaylov <[email protected]>
31
 * @license https://github.com/lmihaylov2512/pass-generator/blob/master/LICENSE.md MIT License
32
 */
33
class Generator
34
{
35
    /**
36
     * @var integer default minimum password size
37
     */
38
    const DEFAULT_MIN_LENGTH = 6;
39
    /**
40
     * @var integer default maximum password size
41
     */
42
    const DEFAULT_MAX_LENGTH = 32;
43
    
44
    /**
45
     * @var Detector environment detector instance
46
     */
47
    protected $detector;
48
    /**
49
     * @var array default configurations (key: type => value: configuration)
50
     */
51
    protected $defaults = [
52
        'upperCase' => true,
53
        'lowerCase' => true,
54
        'digits' => true,
55
        'special' => false,
56
        'brackets' => false,
57
        'minus' => false,
58
        'underline' => false,
59
        'space' => false,
60
        'length' => 12,
61
    ];
62
    /**
63
     * @var array data storage
64
     */
65
    protected $data;
66
67
    /**
68
     * Detect environment, apply passed configuration and generate a password, if auto generating is turn on.
69
     * 
70
     * @param array $config configurations array
71
     * @param integer $minLength custom password minimum length
72
     * @param integer $maxLength custom password maximum length
73
     * @param boolean $autoGenerate whether generate password after initialization
74
     */
75
    public function __construct(array $config = [], int $minLength = self::DEFAULT_MIN_LENGTH, int $maxLength = self::DEFAULT_MAX_LENGTH, bool $autoGenerate = true)
76
    {   
77
        //detect environment
78
        $this->detector = new Detector();
79
        
80
        //apply passed configurations
81
        foreach ($config as $key => $val) {
82
            if (array_key_exists($key, $this->defaults)) {
83
                $this->defaults[$key] = !!$val;
84
            } else if (array_key_exists($val, $this->defaults)) {
85
                $this->defaults[$val] = true;
86
            } else if (is_numeric($val) && $val >= $minLength && $val <= $maxLength) {
87
                $this->defaults['length'] = (int) $val;
88
            }
89
        }
90
        
91
        if ($autoGenerate) {
92
            $this->generate();
93
        }
94
    }
95
    
96
    /**
97
     * Get storage value or option according passed key.
98
     * 
99
     * @param string $name specific storage key
100
     * @return mixed the response value
101
     */
102
    public function __get(string $name)
103
    {
104
        if (array_key_exists($name, $this->data)) {
105
            return $this->data[$name];
106
        } else if (array_key_exists($name, $this->defaults)) {
107
            return $this->defaults[$name];
108
        }
109
    }
110
    
111
    /**
112
     * Change configuration type value.
113
     * 
114
     * @param string $name configuration type
115
     * @param boolean|integer $value the new value
116
     * @return void
117
     */
118
    public function __set(string $name, $value)
119
    {
120
        if (array_key_exists($name, $this->defaults)) {
121
            $this->defaults[$name] = ($name === 'length') ? (int) $value : !!$value;
122
        }
123
    }
124
    
125
    /**
126
     * Generate the password based on configuration array.
127
     * 
128
     * @return string the generated password
129
     */
130
    public function generate(): string
131
    {
132
        //initial initilization
133
        $chars = Storage::getCharacters();
134
        $pattern = '';
135
        
136
        foreach ($this->defaults as $type => $val) {
137
            if ($val && isset($chars[$type])) {
138
                $pattern .= $chars[$type];
139
            }
140
        }
141
        
142
        $pattern = str_shuffle($pattern);
143
        $max = strlen($pattern) - 1;
144
        $counter = $this->defaults['length'];
145
        $this->data['password'] = '';
146
        
147
        if ($max < 0) {
148
            return $this->data['password'];
149
        }
150
        
151
        while ($counter > 0) {
152
            $this->data['password'] .= $pattern[mt_rand(0, $max)];
153
            $counter--;
154
        }
155
        
156
        return $this->data['password'];
157
    }
158
}
159
160