DictionaryRule   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 102
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 32
c 1
b 0
f 0
dl 0
loc 102
ccs 34
cts 34
cp 1
rs 10
wmc 12

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getMessage() 0 4 1
A getDictionaryWord() 0 16 4
A test() 0 9 3
A getWordList() 0 3 1
A validate() 0 14 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\PasswordPolice\Rule;
6
7
use RuntimeException;
8
use Stadly\PasswordPolice\CharTree;
9
use Stadly\PasswordPolice\Formatter;
10
use Stadly\PasswordPolice\Formatter\Combiner;
11
use Stadly\PasswordPolice\Rule;
12
use Stadly\PasswordPolice\ValidationError;
13
use Stadly\PasswordPolice\WordList;
14
use Symfony\Contracts\Translation\LocaleAwareInterface;
15
use Symfony\Contracts\Translation\TranslatorInterface;
16
17
final class DictionaryRule implements Rule
18
{
19
    /**
20
     * @var WordList Word list for the dictionary.
21
     */
22
    private $wordList;
23
24
    /**
25
     * @var Formatter Formatter.
26
     */
27
    private $formatter;
28
29
    /**
30
     * @var int Constraint weight.
31
     */
32
    private $weight;
33
34
    /**
35
     * @param WordList $wordList Word list for the dictionary.
36
     * @param array<Formatter> $formatters Formatters.
37
     * @param int $weight Constraint weight.
38
     */
39 13
    public function __construct(WordList $wordList, array $formatters = [], int $weight = 1)
40
    {
41 13
        $this->wordList = $wordList;
42 13
        $this->formatter = new Combiner($formatters);
43 13
        $this->weight = $weight;
44 13
    }
45
46
    /**
47
     * @return WordList Word list for the dictionary.
48
     */
49 1
    public function getWordList(): WordList
50
    {
51 1
        return $this->wordList;
52
    }
53
54
    /**
55
     * @inheritDoc
56
     */
57 10
    public function test($password, ?int $weight = null): bool
58
    {
59 10
        if ($weight !== null && $this->weight < $weight) {
60 1
            return true;
61
        }
62
63 9
        $word = $this->getDictionaryWord((string)$password);
64
65 8
        return $word === null;
66
    }
67
68
    /**
69
     * @inheritDoc
70
     */
71 2
    public function validate($password, TranslatorInterface $translator): ?ValidationError
72
    {
73 2
        $word = $this->getDictionaryWord((string)$password);
74
75 2
        if ($word !== null) {
76 1
            return new ValidationError(
77 1
                $this->getMessage($word, $translator),
78 1
                $password,
79 1
                $this,
80 1
                $this->weight
81
            );
82
        }
83
84 1
        return null;
85
    }
86
87
    /**
88
     * @param string $password Password to find dictionary words in.
89
     * @return string|null Dictionary word in the password.
90
     * @throws CouldNotUseRuleException If an error occurred.
91
     */
92 11
    private function getDictionaryWord(string $password): ?string
93
    {
94 11
        foreach ($this->formatter->apply(CharTree::fromString($password)) as $formattedPassword) {
95
            try {
96 11
                if ($this->wordList->contains($formattedPassword)) {
97 10
                    return $formattedPassword;
98
                }
99 1
            } catch (RuntimeException $exception) {
100 1
                throw new CouldNotUseRuleException(
101 1
                    $this,
102 1
                    'An error occurred while using the word list: ' . $exception->getMessage(),
103 8
                    $exception
104
                );
105
            }
106
        }
107 7
        return null;
108
    }
109
110
    /**
111
     * @param string $word Word that violates the constraint.
112
     * @param TranslatorInterface&LocaleAwareInterface $translator Translator for translating messages.
113
     * @return string Message explaining the violation.
114
     */
115 1
    private function getMessage(string $word, TranslatorInterface $translator): 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

115
    private function getMessage(/** @scrutinizer ignore-unused */ string $word, TranslatorInterface $translator): 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...
116
    {
117 1
        return $translator->trans(
118 1
            'The password cannot contain dictionary words.'
119
        );
120
    }
121
}
122