Completed
Push — master ( 0c8b4d...fe5ddc )
by Magnar Ovedal
02:51
created

DictionaryRule::getFormattedWords()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\PasswordPolice\Rule;
6
7
use RuntimeException;
8
use Stadly\PasswordPolice\Policy;
9
use Stadly\PasswordPolice\Rule;
10
use Stadly\PasswordPolice\ValidationError;
11
use Stadly\PasswordPolice\WordFormatter;
12
use Stadly\PasswordPolice\WordFormatter\FormatterCombiner;
13
use Stadly\PasswordPolice\WordList;
14
use Traversable;
15
16
final class DictionaryRule implements Rule
17
{
18
    /**
19
     * @var WordList Word list for the dictionary.
20
     */
21
    private $wordList;
22
23
    /**
24
     * @var WordFormatter Word formatter.
25
     */
26
    private $wordFormatter;
27
28
    /**
29
     * @var int Constraint weight.
30
     */
31
    private $weight;
32
33
    /**
34
     * @param WordList $wordList Word list for the dictionary.
35
     * @param WordFormatter[] $wordFormatters Word formatters.
36
     * @param int $weight Constraint weight.
37
     */
38 1
    public function __construct(WordList $wordList, array $wordFormatters = [], int $weight = 1)
39
    {
40 1
        $this->wordList = $wordList;
41 1
        $this->wordFormatter = new FormatterCombiner($wordFormatters);
42 1
        $this->weight = $weight;
43 1
    }
44
45
    /**
46
     * @return WordList Word list for the dictionary.
47
     */
48 1
    public function getWordList(): WordList
49
    {
50 1
        return $this->wordList;
51
    }
52
53
    /**
54
     * {@inheritDoc}
55
     */
56 9
    public function test($password, ?int $weight = 1): bool
57
    {
58 9
        if ($weight !== null && $this->weight < $weight) {
59 1
            return true;
60
        }
61
62 8
        $word = $this->getDictionaryWord((string)$password);
63
64 7
        return $word === null;
65
    }
66
67
    /**
68
     * {@inheritDoc}
69
     */
70 2
    public function validate($password): ?ValidationError
71
    {
72 2
        $word = $this->getDictionaryWord((string)$password);
73
74 2
        if ($word !== null) {
75 1
            return new ValidationError(
76 1
                $this->getMessage($word),
77 1
                $password,
78 1
                $this,
79 1
                $this->weight
80
            );
81
        }
82
83 1
        return null;
84
    }
85
86
    /**
87
     * @param string $password Password to find dictionary words in.
88
     * @return string|null DictionaryRule word in the password.
89
     * @throws RuleException If an error occurred.
90
     */
91 10
    private function getDictionaryWord(string $password): ?string
92
    {
93 10
        foreach ($this->wordFormatter->apply([$password]) as $word) {
94
            try {
95 10
                if ($this->wordList->contains($word)) {
96 9
                    return $word;
97
                }
98 1
            } catch (RuntimeException $exception) {
99 1
                throw new RuleException(
100 1
                    $this,
101 1
                    'An error occurred while using the word list: '.$exception->getMessage(),
102 8
                    $exception
103
                );
104
            }
105
        }
106 7
        return null;
107
    }
108
109
    /**
110
     * @param string $word Word that violates the constraint.
111
     * @return string Message explaining the violation.
112
     */
113 1
    private function getMessage(string $word): string
0 ignored issues
show
Unused Code introduced by
The parameter $word is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

113
    private function getMessage(/** @scrutinizer ignore-unused */ string $word): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
114
    {
115 1
        $translator = Policy::getTranslator();
116
117 1
        return $translator->trans(
118 1
            'Must not contain dictionary words.'
119
        );
120
    }
121
}
122