GuessableDataRule::contains()   A
last analyzed

Complexity

Conditions 5
Paths 6

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 8
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 15
ccs 7
cts 7
cp 1
crap 5
rs 9.6111
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stadly\PasswordPolice\Rule;
6
7
use DateTimeInterface;
8
use Stadly\PasswordPolice\CharTree;
9
use Stadly\PasswordPolice\DateFormatter;
10
use Stadly\PasswordPolice\DateFormatter\DefaultFormatter;
11
use Stadly\PasswordPolice\Formatter;
12
use Stadly\PasswordPolice\Formatter\Combiner;
13
use Stadly\PasswordPolice\Password;
14
use Stadly\PasswordPolice\Rule;
15
use Stadly\PasswordPolice\ValidationError;
16
use Symfony\Contracts\Translation\LocaleAwareInterface;
17
use Symfony\Contracts\Translation\TranslatorInterface;
18
19
final class GuessableDataRule implements Rule
20
{
21
    /**
22
     * @var array<string|DateTimeInterface> Guessable data.
23
     */
24
    private $guessableData;
25
26
    /**
27
     * @var Formatter Formatter.
28
     */
29
    private $formatter;
30
31
    /**
32
     * @var DateFormatter Date formatter.
33
     */
34
    private $dateFormatter;
35
36
    /**
37
     * @var int Constraint weight.
38
     */
39
    private $weight;
40
41
    /**
42
     * @param array<string|DateTimeInterface> $guessableData Guessable data.
43
     * @param array<Formatter> $formatters Formatters.
44
     * @param DateFormatter|null $dateFormatter Date formatter.
45
     * @param int $weight Constraint weight.
46
     */
47 19
    public function __construct(
48
        array $guessableData = [],
49
        array $formatters = [],
50
        ?DateFormatter $dateFormatter = null,
51
        int $weight = 1
52
    ) {
53 19
        $this->guessableData = $guessableData;
54 19
        $this->formatter = new Combiner($formatters);
55 19
        $this->dateFormatter = $dateFormatter ?? new DefaultFormatter();
56 19
        $this->weight = $weight;
57 19
    }
58
59
    /**
60
     * Check whether a password is in compliance with the rule.
61
     *
62
     * @param Password|string $password Password to check.
63
     * @param int|null $weight Don't consider constraints with lower weights.
64
     * @return bool Whether the password is in compliance with the rule.
65
     */
66 17
    public function test($password, ?int $weight = null): bool
67
    {
68 17
        if ($weight !== null && $this->weight < $weight) {
69 1
            return true;
70
        }
71
72 16
        $data = $this->getGuessableData($password);
73
74 16
        return $data === null;
75
    }
76
77
    /**
78
     * Validate that a password is in compliance with the rule.
79
     *
80
     * @param Password|string $password Password to validate.
81
     * @param TranslatorInterface&LocaleAwareInterface $translator Translator for translating messages.
82
     * @return ValidationError|null Validation error describing why the password is not in compliance with the rule.
83
     */
84 2
    public function validate($password, TranslatorInterface $translator): ?ValidationError
85
    {
86 2
        $data = $this->getGuessableData($password);
87
88 2
        if ($data !== null) {
89 1
            return new ValidationError(
90 1
                $this->getMessage($data, $translator),
91 1
                $password,
92 1
                $this,
93 1
                $this->weight
94
            );
95
        }
96
97 1
        return null;
98
    }
99
100
    /**
101
     * @param Password|string $password Password to find guessable data in.
102
     * @return string|DateTimeInterface|null Guessable data in the password.
103
     */
104 18
    private function getGuessableData($password)
105
    {
106 18
        $guessableData = $this->guessableData;
107 18
        if ($password instanceof Password) {
108 17
            $guessableData = array_merge($guessableData, $password->getGuessableData());
109
        }
110
111 18
        $formattedPassword = $this->formatter->apply(CharTree::fromString((string)$password));
112 18
        foreach ($guessableData as $data) {
113 17
            if ($this->contains($formattedPassword, $data)) {
114 18
                return $data;
115
            }
116
        }
117
118
        return null;
119 10
    }
120
121
    /**
122
     * @param CharTree $formattedPassword Formatted password to check.
123
     * @param string|DateTimeInterface $data Data to check.
124
     * @return bool Whether the password contains the data.
125
     */
126
    private function contains(CharTree $formattedPassword, $data): bool
127 17
    {
128
        if ($data instanceof DateTimeInterface) {
129 17
            $charTree = $this->dateFormatter->apply([$data]);
130 7
        } else {
131
            $charTree = CharTree::fromString($data);
132 11
        }
133
134
        foreach ($charTree as $string) {
135 17
            if ($string !== '' && $formattedPassword->contains($string, /*ignoreCase*/true)) {
136 17
                return true;
137 17
            }
138
        }
139
140
        return false;
141 10
    }
142
143
    /**
144
     * @param string|DateTimeInterface $data Data that violates the constraint.
145
     * @param TranslatorInterface&LocaleAwareInterface $translator Translator for translating messages.
146
     * @return string Message explaining the violation.
147
     */
148
    private function getMessage($data, TranslatorInterface $translator): string
0 ignored issues
show
Unused Code introduced by
The parameter $data 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

148
    private function getMessage(/** @scrutinizer ignore-unused */ $data, 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...
149 1
    {
150
        return $translator->trans(
151 1
            'The password cannot contain words that are easy to guess.'
152 1
        );
153
    }
154
}
155