Factory::findMixer()   C
last analyzed

Complexity

Conditions 7
Paths 15

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 24
rs 6.7272
cc 7
eloc 15
nc 15
nop 1
1
<?php
2
3
/*
4
 * The RandomLib library for securely generating random numbers and strings in PHP
5
 *
6
 * @author     Anthony Ferrara <[email protected]>
7
 * @copyright  2011 The Authors
8
 * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
9
 * @version    Build @@version@@
10
 */
11
12
/**
13
 * The Random Factory
14
 *
15
 * Use this factory to instantiate random number generators, sources and mixers.
16
 *
17
 * PHP version 5.3
18
 *
19
 * @category   PHPPasswordLib
20
 * @package    Random
21
 *
22
 * @author     Anthony Ferrara <[email protected]>
23
 * @copyright  2011 The Authors
24
 * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
25
 *
26
 * @version    Build @@version@@
27
 */
28
namespace RandomLib;
29
30
use SecurityLib\Strength;
31
32
/**
33
 * The Random Factory
34
 *
35
 * Use this factory to instantiate random number generators, sources and mixers.
36
 *
37
 * @category   PHPPasswordLib
38
 * @package    Random
39
 *
40
 * @author     Anthony Ferrara <[email protected]>
41
 */
42
class Factory extends \SecurityLib\AbstractFactory
43
{
44
45
    /**
46
     * @var array A list of available random number mixing strategies
47
     */
48
    protected $mixers = array();
49
50
    /**
51
     * @var array A list of available random number sources
52
     */
53
    protected $sources = array();
54
55
    /**
56
     * Build a new instance of the factory, loading core mixers and sources
57
     *
58
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
59
     */
60
    public function __construct()
61
    {
62
        $this->loadMixers();
63
        $this->loadSources();
64
    }
65
66
    /**
67
     * Get a generator for the requested strength
68
     *
69
     * @param Strength $strength The requested strength of the random number
70
     *
71
     * @throws RuntimeException If an appropriate mixing strategy isn't found
72
     *
73
     * @return Generator The instantiated generator
74
     */
75
    public function getGenerator(\SecurityLib\Strength $strength)
76
    {
77
        $sources = $this->findSources($strength);
78
        $mixer   = $this->findMixer($strength);
79
80
        return new Generator($sources, $mixer);
81
    }
82
83
    /**
84
     * Get a high strength random number generator
85
     *
86
     * High Strength keys should ONLY be used for generating extremely strong
87
     * cryptographic keys.  Generating them is very resource intensive and may
88
     * take several minutes or more depending on the requested size.
89
     *
90
     * @return Generator The instantiated generator
91
     */
92
    public function getHighStrengthGenerator()
93
    {
94
        return $this->getGenerator(new Strength(Strength::HIGH));
95
    }
96
97
    /**
98
     * Get a low strength random number generator
99
     *
100
     * Low Strength should be used anywhere that random strings are needed in a
101
     * non-cryptographical setting.  They are not strong enough to be used as
102
     * keys or salts.  They are however useful for one-time use tokens.
103
     *
104
     * @return Generator The instantiated generator
105
     */
106
    public function getLowStrengthGenerator()
107
    {
108
        return $this->getGenerator(new Strength(Strength::LOW));
109
    }
110
111
    /**
112
     * Get a medium strength random number generator
113
     *
114
     * Medium Strength should be used for most needs of a cryptographic nature.
115
     * They are strong enough to be used as keys and salts.  However, they do
116
     * take some time and resources to generate, so they should not be over-used
117
     *
118
     * @return Generator The instantiated generator
119
     */
120
    public function getMediumStrengthGenerator()
121
    {
122
        return $this->getGenerator(new Strength(Strength::MEDIUM));
123
    }
124
125
    /**
126
     * Get all loaded mixing strategies
127
     *
128
     * @return array An array of mixers
129
     */
130
    public function getMixers()
131
    {
132
        return $this->mixers;
133
    }
134
135
    /**
136
     * Get all loaded random number sources
137
     *
138
     * @return array An array of sources
139
     */
140
    public function getSources()
141
    {
142
        return $this->sources;
143
    }
144
145
    /**
146
     * Register a mixing strategy for this factory instance
147
     *
148
     * @param string $name  The name of the stategy
149
     * @param string $class The class name of the implementation
150
     *
151
     * @return Factory $this The current factory instance
152
     */
153
    public function registerMixer($name, $class)
154
    {
155
        $this->registerType(
156
            'mixers',
157
            __NAMESPACE__ . '\\Mixer',
158
            $name,
159
            $class
160
        );
161
162
        return $this;
163
    }
164
165
    /**
166
     * Register a random number source for this factory instance
167
     *
168
     * Note that this class must implement the Source interface
169
     *
170
     * @param string $name  The name of the stategy
171
     * @param string $class The class name of the implementation
172
     *
173
     * @return Factory $this The current factory instance
174
     */
175
    public function registerSource($name, $class)
176
    {
177
        $this->registerType(
178
            'sources',
179
            __NAMESPACE__ . '\\Source',
180
            $name,
181
            $class
182
        );
183
184
        return $this;
185
    }
186
187
    /**
188
     * Find a sources based upon the requested strength
189
     *
190
     * @param Strength $strength The strength mixer to find
191
     *
192
     * @throws RuntimeException if a valid source cannot be found
193
     *
194
     * @return Source The found source
0 ignored issues
show
Documentation introduced by
Should the return type not be array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
195
     */
196
    protected function findSources(\SecurityLib\Strength $strength)
197
    {
198
        $sources = array();
199
        foreach ($this->getSources() as $source) {
200
            if ($strength->compare($source::getStrength()) <= 0 && $source::isSupported()) {
201
                $sources[] = new $source();
202
            }
203
        }
204
205
        if (0 === count($sources)) {
206
            throw new \RuntimeException('Could not find sources');
207
        }
208
209
        return $sources;
210
    }
211
212
    /**
213
     * Find a mixer based upon the requested strength
214
     *
215
     * @param Strength $strength The strength mixer to find
216
     *
217
     * @throws RuntimeException if a valid mixer cannot be found
218
     *
219
     * @return Mixer The found mixer
220
     */
221
    protected function findMixer(\SecurityLib\Strength $strength)
222
    {
223
        $newMixer = null;
224
        $fallback = null;
225
        foreach ($this->getMixers() as $mixer) {
226
            if (!$mixer::test()) {
227
                continue;
228
            }
229
            if ($strength->compare($mixer::getStrength()) == 0) {
230
                $newMixer = new $mixer();
231
            } elseif ($strength->compare($mixer::getStrength()) == 1) {
232
                $fallback = new $mixer();
233
            }
234
        }
235
        if (is_null($newMixer)) {
236
            if (is_null($fallback)) {
237
                throw new \RuntimeException('Could not find mixer');
238
            }
239
240
            return $fallback;
241
        }
242
243
        return $newMixer;
244
    }
245
246
    /**
247
     * Load all core mixing strategies
248
     *
249
     * @return void
250
     */
251
    protected function loadMixers()
252
    {
253
        $this->loadFiles(
254
            __DIR__ . '/Mixer',
255
            __NAMESPACE__ . '\\Mixer\\',
256
            array($this, 'registerMixer')
0 ignored issues
show
Documentation introduced by
array($this, 'registerMixer') is of type array<integer,this<Rando...actory>","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
257
        );
258
    }
259
260
    /**
261
     * Load all core random number sources
262
     *
263
     * @return void
264
     */
265
    protected function loadSources()
266
    {
267
        $this->loadFiles(
268
            __DIR__ . '/Source',
269
            __NAMESPACE__ . '\\Source\\',
270
            array($this, 'registerSource')
0 ignored issues
show
Documentation introduced by
array($this, 'registerSource') is of type array<integer,this<Rando...actory>","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
271
        );
272
    }
273
}
274