SequencialNumber::find()   A
last analyzed

Complexity

Conditions 5
Paths 9

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.6111
cc 5
nc 9
nop 3
crap 5
1
<?php
2
/*
3
    Password Strength Library
4
    Copyright (C) 2019 CustomerGauge
5
    [email protected]
6
7
    This program is free software; you can redistribute it and/or
8
    modify it under the terms of the GNU Lesser General Public
9
    License as published by the Free Software Foundation; either
10
    version 3 of the License, or (at your option) any later version.
11
12
    This program is distributed in the hope that it will be useful,
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
    Lesser General Public License for more details.
16
17
    You should have received a copy of the GNU Lesser General Public License
18
    along with this program; if not, write to the Free Software Foundation,
19
    Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
*/
21
22
declare(strict_types=1);
23
24
namespace CustomerGauge\Password\Rule;
25
26
use CustomerGauge\Password\Exception\SequencialNumber as SequencialNumberException;
27
use CustomerGauge\Password\Rule;
28
29
use function mb_strlen;
30
31
final class SequencialNumber implements Rule
32
{
33
    public const ASCENDING  = 'ASC';
34
    public const DESCENDING = 'DESC';
35
36
    private int $count;
37
38
    private string $encoding;
39
40 2
    public function __construct(int $count = 3, string $encoding = 'utf8')
41
    {
42 2
        $this->count    = $count;
43 2
        $this->encoding = $encoding;
44 2
    }
45
46 2
    public function __invoke(string $password): void
47
    {
48 2
        $length = (int) mb_strlen($password, $this->encoding);
49
50 2
        $this->find($password, $length, self::ASCENDING);
51 1
        $this->find($password, $length, self::DESCENDING);
52
    }
53
54 2
    private function find(string $password, int $length, string $direction): void
55
    {
56 2
        $chained = 1;
57
58 2
        for ($i = 1; $i < $length; $i++) {
59 2
            $current  = (int) $password[$i];
60 2
            $previous = (int) $password[$i - 1];
61
62 2
            $direction === self::ASCENDING ? $previous++ : $previous--;
63
64 2
            $current === $previous ? $chained++ : $chained = 1;
65
66 2
            if ($chained === $this->count) {
67 2
                throw SequencialNumberException::notAllowed();
68
            }
69
        }
70 1
    }
71
}
72