MemberName   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 84
ccs 27
cts 27
cp 1
rs 10
wmc 9

3 Methods

Rating   Name   Duplication   Size   Complexity  
A default() 0 3 1
B handle() 0 40 7
A __construct() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace VGirol\JsonApiStructure\Constraint;
6
7
use VGirol\JsonApiStructure\Messages;
8
9
/**
10
 * Constraint that checks if a name is a valid member name.
11
 */
12
class MemberName extends Constraint
13
{
14
    /**
15
     * Undocumented variable
16
     *
17
     * @var bool
18
     */
19
    private $strict;
20
21
    /**
22
     * Class constructor.
23
     *
24
     * @param boolean $strict If true, unsafe characters are not allowed when checking members name.
25
     */
26 225
    public function __construct(bool $strict)
27
    {
28 225
        $this->strict = $strict;
29 225
    }
30
31
    /**
32
     * Returns a string representation of the constraint.
33
     */
34 81
    public function default(): string
35
    {
36 81
        return Messages::MEMBER_NAME_NOT_VALID;
37
    }
38
39
    /**
40
     * Evaluates the constraint for parameter $json. Returns true if the constraint is met, false otherwise.
41
     *
42
     * Asserts that a member name is valid.
43
     *
44
     * It will do the following checks :
45
     * 1) asserts that the name is a string with at least one character.
46
     * 2) asserts that the name has only allowed characters.
47
     * 3) asserts that it starts and ends with a globally allowed character.
48
     *
49
     * @link https://jsonapi.org/format/#document-member-names-allowed-characters
50
     *
51
     * @param mixed $name Value or object to evaluate
52
     *
53
     * @return bool
54
     * @throws \VGirol\JsonApiStructure\Exception\ValidationException
55
     */
56 225
    public function handle($name): bool
57
    {
58 225
        if (!\is_string($name)) {
59 3
            $this->setFailureMessage(Messages::MEMBER_NAME_MUST_BE_STRING);
60
61 3
            return false;
62
        }
63
64 222
        if (\strlen($name) < 1) {
65 3
            $this->setFailureMessage(Messages::MEMBER_NAME_IS_TOO_SHORT);
66
67 3
            return false;
68
        }
69
70
        // Globally allowed characters
71 219
        $globally = '\x{0030}-\x{0039}\x{0041}-\x{005A}\x{0061}-\x{007A}';
72 219
        $globallyNotSafe = '\x{0080}-\x{FFFF}';
73
74
        // Allowed characters
75 219
        $allowed = '\x{002D}\x{005F}';
76 219
        $allowedNotSafe = '\x{0020}';
77
78 219
        $regex = "/[^{$globally}{$globallyNotSafe}{$allowed}{$allowedNotSafe}]+/u";
79 219
        $safeRegex = "/[^{$globally}{$allowed}]+/u";
80
81 219
        if (\preg_match($this->strict ? $safeRegex : $regex, $name) > 0) {
82 69
            $this->setFailureMessage(Messages::MEMBER_NAME_MUST_NOT_HAVE_RESERVED_CHARACTERS);
83
84 69
            return false;
85
        }
86
87 168
        $regex = "/^[{$globally}{$globallyNotSafe}]{1}(?:.*[{$globally}{$globallyNotSafe}]{1})?$/u";
88 168
        $safeRegex = "/^[{$globally}]{1}(?:.*[{$globally}]{1})?$/u";
89 168
        if (\preg_match($this->strict ? $safeRegex : $regex, $name) == 0) {
90 6
            $this->setFailureMessage(Messages::MEMBER_NAME_MUST_START_AND_END_WITH_ALLOWED_CHARACTERS);
91
92 6
            return false;
93
        }
94
95 162
        return true;
96
    }
97
}
98