Passed
Pull Request — master (#20)
by Hilmi Erdem
13:59 queued 07:56
created

GeneratorManager::get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
/*
3
 * Copyright (c) 2021. Hilmi Erdem Keren
4
 * license MIT
5
 */
6
7
namespace Erdemkeren\Otp;
8
9
use Erdemkeren\Otp\Contracts\GeneratorContract;
10
use Erdemkeren\Otp\Contracts\GeneratorManagerContract;
11
use Erdemkeren\Otp\Exceptions\GeneratorInstantiationException;
12
use Erdemkeren\Otp\Exceptions\UnregisteredGeneratorException;
13
use function is_callable;
14
use function is_string;
15
use ReflectionClass;
16
use UnexpectedValueException;
17
18
/**
19
 * Class GeneratorManager.
20
 */
21
class GeneratorManager implements GeneratorManagerContract
22
{
23
    /**
24
     * The password generator registry.
25
     *
26
     * @var array
27
     */
28
    private static array $generators;
29
30
    /**
31
     * Get the token generator by the given name.
32
     *
33
     * @param  string  $name
34
     * @return callable
35
     *
36
     * @throws UnregisteredGeneratorException
37
     */
38
    public function get(string $name): callable
39
    {
40
        if (! array_key_exists($name, static::$generators)) {
0 ignored issues
show
Bug introduced by
Since $generators is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $generators to at least protected.
Loading history...
41
            throw UnregisteredGeneratorException::createForName($name);
42
        }
43
44
        return static::$generators[$name];
45
    }
46
47
    /**
48
     * Registers the given password generator with the given name.
49
     *
50
     * @param  string  $name
51
     * @param  callable|string  $generator
52
     */
53
    public function register(string $name, string|callable $generator): void
54
    {
55
        if (is_string($generator)) {
56
            $generator = $this->createGeneratorFromString($generator);
57
        }
58
59
        if (! is_callable($generator) && ! $generator instanceof GeneratorContract) {
60
            throw new UnexpectedValueException(sprintf(
61
                'The generators should either be callable or an instance of %s',
62
                GeneratorContract::class,
63
            ));
64
        }
65
66
        static::$generators[$name] = is_callable($generator)
0 ignored issues
show
Bug introduced by
Since $generators is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $generators to at least protected.
Loading history...
67
            ? $generator
68
            : function () use ($generator): string {
69
                return $generator->generate();
70
            };
71
    }
72
73
    /**
74
     * Create a new password generator instance using the given
75
     * fully qualified password generator class name.
76
     *
77
     * @param  string  $className
78
     * @return GeneratorContract
79
     */
80
    private function createGeneratorFromString(string $className): GeneratorContract
81
    {
82
        if (! class_exists($className)) {
83
            throw GeneratorInstantiationException::createForMissingGenerator($className);
84
        }
85
86
        $generatorReflection = new ReflectionClass($className);
87
        if (! $generatorReflection->isInstantiable()) {
88
            throw GeneratorInstantiationException::createForNotInstantiableGenerator($className);
89
        }
90
91
        return new $className();
92
    }
93
}
94