Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace OTPHP;
6
 
1441 ariadna 7
use InvalidArgumentException;
8
use function array_key_exists;
9
use function assert;
10
use function in_array;
11
use function is_int;
12
use function is_string;
1 efrain 13
 
14
trait ParameterTrait
15
{
16
    /**
1441 ariadna 17
     * @var array<non-empty-string, mixed>
1 efrain 18
     */
1441 ariadna 19
    private array $parameters = [];
1 efrain 20
 
21
    /**
1441 ariadna 22
     * @var non-empty-string|null
1 efrain 23
     */
1441 ariadna 24
    private null|string $issuer = null;
1 efrain 25
 
26
    /**
1441 ariadna 27
     * @var non-empty-string|null
1 efrain 28
     */
1441 ariadna 29
    private null|string $label = null;
1 efrain 30
 
1441 ariadna 31
    private bool $issuer_included_as_parameter = true;
1 efrain 32
 
33
    /**
1441 ariadna 34
     * @return array<non-empty-string, mixed>
1 efrain 35
     */
36
    public function getParameters(): array
37
    {
38
        $parameters = $this->parameters;
39
 
1441 ariadna 40
        if ($this->getIssuer() !== null && $this->isIssuerIncludedAsParameter() === true) {
1 efrain 41
            $parameters['issuer'] = $this->getIssuer();
42
        }
43
 
44
        return $parameters;
45
    }
46
 
47
    public function getSecret(): string
48
    {
1441 ariadna 49
        $value = $this->getParameter('secret');
50
        (is_string($value) && $value !== '') || throw new InvalidArgumentException('Invalid "secret" parameter.');
1 efrain 51
 
1441 ariadna 52
        return $value;
1 efrain 53
    }
54
 
1441 ariadna 55
    public function getLabel(): null|string
1 efrain 56
    {
57
        return $this->label;
58
    }
59
 
1441 ariadna 60
    public function setLabel(string $label): void
1 efrain 61
    {
62
        $this->setParameter('label', $label);
63
    }
64
 
1441 ariadna 65
    public function getIssuer(): null|string
1 efrain 66
    {
67
        return $this->issuer;
68
    }
69
 
1441 ariadna 70
    public function setIssuer(string $issuer): void
1 efrain 71
    {
72
        $this->setParameter('issuer', $issuer);
73
    }
74
 
75
    public function isIssuerIncludedAsParameter(): bool
76
    {
77
        return $this->issuer_included_as_parameter;
78
    }
79
 
1441 ariadna 80
    public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter): void
1 efrain 81
    {
82
        $this->issuer_included_as_parameter = $issuer_included_as_parameter;
83
    }
84
 
85
    public function getDigits(): int
86
    {
1441 ariadna 87
        $value = $this->getParameter('digits');
88
        (is_int($value) && $value > 0) || throw new InvalidArgumentException('Invalid "digits" parameter.');
1 efrain 89
 
1441 ariadna 90
        return $value;
1 efrain 91
    }
92
 
93
    public function getDigest(): string
94
    {
1441 ariadna 95
        $value = $this->getParameter('algorithm');
96
        (is_string($value) && $value !== '') || throw new InvalidArgumentException('Invalid "algorithm" parameter.');
1 efrain 97
 
1441 ariadna 98
        return $value;
1 efrain 99
    }
100
 
101
    public function hasParameter(string $parameter): bool
102
    {
103
        return array_key_exists($parameter, $this->parameters);
104
    }
105
 
1441 ariadna 106
    public function getParameter(string $parameter): mixed
1 efrain 107
    {
108
        if ($this->hasParameter($parameter)) {
109
            return $this->getParameters()[$parameter];
110
        }
111
 
1441 ariadna 112
        throw new InvalidArgumentException(sprintf('Parameter "%s" does not exist', $parameter));
1 efrain 113
    }
114
 
1441 ariadna 115
    public function setParameter(string $parameter, mixed $value): void
1 efrain 116
    {
117
        $map = $this->getParameterMap();
118
 
1441 ariadna 119
        if (array_key_exists($parameter, $map) === true) {
1 efrain 120
            $callback = $map[$parameter];
121
            $value = $callback($value);
122
        }
123
 
124
        if (property_exists($this, $parameter)) {
1441 ariadna 125
            $this->{$parameter} = $value;
1 efrain 126
        } else {
127
            $this->parameters[$parameter] = $value;
128
        }
129
    }
130
 
1441 ariadna 131
    public function setSecret(string $secret): void
132
    {
133
        $this->setParameter('secret', $secret);
134
    }
135
 
136
    public function setDigits(int $digits): void
137
    {
138
        $this->setParameter('digits', $digits);
139
    }
140
 
141
    public function setDigest(string $digest): void
142
    {
143
        $this->setParameter('algorithm', $digest);
144
    }
145
 
1 efrain 146
    /**
1441 ariadna 147
     * @return array<non-empty-string, callable>
1 efrain 148
     */
149
    protected function getParameterMap(): array
150
    {
151
        return [
1441 ariadna 152
            'label' => function (string $value): string {
153
                assert($value !== '');
154
                $this->hasColon($value) === false || throw new InvalidArgumentException(
155
                    'Label must not contain a colon.'
156
                );
1 efrain 157
 
158
                return $value;
159
            },
1441 ariadna 160
            'secret' => static fn (string $value): string => mb_strtoupper(trim($value, '=')),
161
            'algorithm' => static function (string $value): string {
162
                $value = mb_strtolower($value);
163
                in_array($value, hash_algos(), true) || throw new InvalidArgumentException(sprintf(
164
                    'The "%s" digest is not supported.',
165
                    $value
166
                ));
1 efrain 167
 
168
                return $value;
169
            },
1441 ariadna 170
            'digits' => static function ($value): int {
171
                $value > 0 || throw new InvalidArgumentException('Digits must be at least 1.');
1 efrain 172
 
173
                return (int) $value;
174
            },
1441 ariadna 175
            'issuer' => function (string $value): string {
176
                assert($value !== '');
177
                $this->hasColon($value) === false || throw new InvalidArgumentException(
178
                    'Issuer must not contain a colon.'
179
                );
1 efrain 180
 
181
                return $value;
182
            },
183
        ];
184
    }
185
 
186
    /**
1441 ariadna 187
     * @param non-empty-string $value
1 efrain 188
     */
1441 ariadna 189
    private function hasColon(string $value): bool
1 efrain 190
    {
191
        $colons = [':', '%3A', '%3a'];
192
        foreach ($colons as $colon) {
1441 ariadna 193
            if (str_contains($value, $colon)) {
1 efrain 194
                return true;
195
            }
196
        }
197
 
198
        return false;
199
    }
200
}