Passed
Push — master ( 9e7e6b...999440 )
by Dedipyaman
01:53
created

PasswordValidator::validate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 2
dl 0
loc 21
rs 9.9332
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Phypes\Validator;
5
6
use Phypes\Error\TypeError\TypeError;
7
use Phypes\Error\TypeError\TypeErrorCode;
8
use Phypes\Result;
9
use Phypes\Rule\String\MinimumLength;
10
11
class PasswordValidator extends AbstractValidator
12
{
13
    /**
14
     * Check if the password has a diverse character type set for a strong-enough password
15
     * Uppercase, lowercase combo etc.
16
     * @param string $password
17
     * @return bool
18
     */
19
    private function hasMultiCharTypes(string $password): bool
20
    {
21
        $differentCharacterTypes = 0;
22
        // Lowercase
23
        if (preg_match('/[a-z]/', $password)) {
24
            $differentCharacterTypes++;
25
        }
26
27
        // Upper case
28
        if (preg_match('/[A-Z]/', $password)) {
29
            $differentCharacterTypes++;
30
        }
31
32
        //Check for numbers
33
        if (preg_match('/[\d]/', $password)) {
34
            $differentCharacterTypes++;
35
        }
36
37
        //Check for anything that's not a word aka special characters
38
        if (preg_match('/[\W]/', $password)) {
39
            $differentCharacterTypes++;
40
        }
41
        return $differentCharacterTypes > 2;
42
    }
43
44
    /**
45
     * Standard password length check
46
     * @param string $password
47
     * @param int $minSize
48
     * @return bool
49
     */
50
    private function isLongEnough(string $password, int $minSize) : bool
51
    {
52
        return (new MinimumLength($minSize))->$this->validate($password)->isValid();
53
    }
54
55
    /**
56
     * Validate the password based on different imposing conditions
57
     * Implement your own password validator if you want a more custom set of rules
58
     * This set of rules should work for a lot of general use cases
59
     * @param $password
60
     * @param array $options
61
     * @return Result
62
     */
63
    public function validate($password, $options = []): Result
64
    {
65
66
        if (!$this->isLongEnough($password, 8)) {
67
68
            $error = new TypeError(TypeErrorCode::PASSWORD_TOO_SMALL,
69
                'The password is not at least 8 characters long');
70
71
            return $this->failure($error);
72
        }
73
74
        if (!$this->hasMultiCharTypes($password)) {
75
76
            $error = new TypeError(TypeErrorCode::PASSWORD_NOT_MULTI_CHARACTER,
77
                'The password does not contain at least 3 of these character types:' .
78
                ' lower case, upper case, numeric and special characters');
79
80
            return $this->failure($error);
81
        }
82
83
        return $this->success();
84
    }
85
}