Isbn::isbn10()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 18
nc 5
nop 1
dl 0
loc 27
ccs 18
cts 18
cp 1
crap 4
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace Mbright\Validation\Rule\Validate;
4
5
class Isbn implements ValidateRuleInterface
6
{
7
    /**
8
     * Validates that the value represents an ISBN.
9
     *
10
     * @param object $subject The subject to be filtered.
11
     * @param string $field The subject field name.
12
     *
13
     * @return bool True if valid, false if not.
14
     */
15 60
    public function __invoke($subject, string $field): bool
16
    {
17 60
        $value = $this->normalize($subject, $field);
18 60
        if (!$value) {
19 3
            return false;
20
        }
21
22 57
        return $this->isbn13($value) || $this->isbn10($value);
23
    }
24
25
    /**
26
     * Removes all non-ISBN characters to test if it is a valid ISBN.
27
     *
28
     * @param object $subject The subject to be filtered.
29
     * @param string $field The subject field name.
30
     *
31
     * @return string|false The normalized string, or false on failure.
32
     */
33 60
    public function normalize($subject, $field)
34
    {
35 60
        $value = preg_replace('/(?:(?!([0-9|X$])).)*/', '', $subject->$field);
36 60
        if (preg_match('/^[0-9]{10,13}$|^[0-9]{9}X$/', $value)) {
37 57
            return $value;
38
        }
39 3
        return false;
40
    }
41
42
    /**
43
     * Tests if a 13 digit ISBN is correct.
44
     *
45
     * @param mixed $value The value to test.
46
     *
47
     * @return bool
48
     */
49 57
    protected function isbn13($value)
50
    {
51 57
        if (strlen($value) != 13) {
52 42
            return false;
53
        }
54
55 15
        $even = $value{0} + $value{2} + $value{4} + $value{6} + $value{8} + $value{10} + $value{12};
56 15
        $odd = $value{1} + $value{3} + $value{5} + $value{7} + $value{9} + $value{11};
57 15
        $sum = $even + ($odd * 3);
58
59 15
        if ($sum % 10) {
60 6
            return false;
61
        }
62
63 9
        return true;
64
    }
65
66
    /**
67
     * Tests if a 10 digit ISBN is correct.
68
     *
69
     * @param mixed $value The value to test.
70
     *
71
     * @return bool
72
     */
73 48
    protected function isbn10($value)
74
    {
75 48
        if (strlen($value) != 10) {
76 6
            return false;
77
        }
78
79 42
        $sum = $value{0}
80 42
            + $value{1} * 2
81 42
            + $value{2} * 3
82 42
            + $value{3} * 4
83 42
            + $value{4} * 5
84 42
            + $value{5} * 6
85 42
            + $value{6} * 7
86 42
            + $value{7} * 8
87 42
            + $value{8} * 9;
88
89 42
        if ($value{9} == 'X') {
90 9
            $sum += 100;
91
        } else {
92 33
            $sum += $value{9} * 10;
93
        }
94
95 42
        if ($sum % 11) {
96 3
            return false;
97
        }
98
99 39
        return true;
100
    }
101
}
102