19
19
* Validates whether the value is a valid ISBN-10 or ISBN-13.
20
20
*
21
21
* @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
22
+ * @author Bernhard Schussek <bschussek@gmail.com>
22
23
*
23
24
* @see https://en.wikipedia.org/wiki/Isbn
24
25
*/
@@ -37,53 +38,71 @@ public function validate($value, Constraint $constraint)
37
38
throw new UnexpectedTypeException ($ value , 'string ' );
38
39
}
39
40
40
- if (!is_numeric ($ value )) {
41
- $ value = str_replace ('- ' , '' , $ value );
42
- }
41
+ $ value = (string ) $ value ;
42
+ $ canonical = strtoupper (str_replace ('- ' , '' , $ value ));
43
43
44
- $ validation = 0 ;
45
- $ value = strtoupper ($ value );
46
- $ valueLength = strlen ($ value );
47
-
48
- if (10 === $ valueLength && null !== $ constraint ->isbn10 ) {
49
- for ($ i = 0 ; $ i < 10 ; $ i ++) {
50
- if ($ value [$ i ] == 'X ' ) {
51
- $ validation += 10 * intval (10 - $ i );
52
- } else {
53
- $ validation += intval ($ value [$ i ]) * intval (10 - $ i );
54
- }
55
- }
44
+ if ($ constraint ->isbn10 && $ this ->isValidIsbn10 ($ canonical )) {
45
+ return ;
46
+ }
56
47
57
- if ($ validation % 11 != 0 ) {
58
- if (null !== $ constraint ->isbn13 ) {
59
- $ this ->context ->addViolation ($ constraint ->bothIsbnMessage );
60
- } else {
61
- $ this ->context ->addViolation ($ constraint ->isbn10Message );
62
- }
63
- }
64
- } elseif (13 === $ valueLength && null !== $ constraint ->isbn13 ) {
65
- for ($ i = 0 ; $ i < 13 ; $ i += 2 ) {
66
- $ validation += intval ($ value [$ i ]);
67
- }
68
- for ($ i = 1 ; $ i < 12 ; $ i += 2 ) {
69
- $ validation += intval ($ value [$ i ]) * 3 ;
70
- }
48
+ if ($ constraint ->isbn13 && $ this ->isValidIsbn13 ($ canonical )) {
49
+ return ;
50
+ }
71
51
72
- if ($ validation % 10 != 0 ) {
73
- if (null !== $ constraint ->isbn10 ) {
74
- $ this ->context ->addViolation ($ constraint ->bothIsbnMessage );
75
- } else {
76
- $ this ->context ->addViolation ($ constraint ->isbn13Message );
77
- }
78
- }
52
+ if ($ constraint ->isbn10 && $ constraint ->isbn13 ) {
53
+ $ this ->context ->addViolation ($ constraint ->bothIsbnMessage , array (
54
+ '{{ value }} ' => $ value ,
55
+ ));
56
+ } elseif ($ constraint ->isbn10 ) {
57
+ $ this ->context ->addViolation ($ constraint ->isbn10Message , array (
58
+ '{{ value }} ' => $ value ,
59
+ ));
79
60
} else {
80
- if (null !== $ constraint ->isbn10 && null !== $ constraint ->isbn13 ) {
81
- $ this ->context ->addViolation ($ constraint ->bothIsbnMessage );
82
- } elseif (null !== $ constraint ->isbn10 ) {
83
- $ this ->context ->addViolation ($ constraint ->isbn10Message );
61
+ $ this ->context ->addViolation ($ constraint ->isbn13Message , array (
62
+ '{{ value }} ' => $ value ,
63
+ ));
64
+ }
65
+ }
66
+
67
+ private function isValidIsbn10 ($ isbn )
68
+ {
69
+ if (10 !== strlen ($ isbn )) {
70
+ return false ;
71
+ }
72
+
73
+ $ checkSum = 0 ;
74
+
75
+ for ($ i = 0 ; $ i < 10 ; ++$ i ) {
76
+ if ('X ' === $ isbn {$ i}) {
77
+ $ digit = 10 ;
78
+ } elseif (ctype_digit($ isbn {$ i })) {
79
+ $ digit = $ isbn {$ i };
84
80
} else {
85
- $ this -> context -> addViolation ( $ constraint -> isbn13Message ) ;
81
+ return false ;
86
82
}
83
+
84
+ $ checkSum += $ digit * intval (10 - $ i );
85
+ }
86
+
87
+ return 0 === $ checkSum % 11 ;
88
+ }
89
+
90
+ private function isValidIsbn13 ($ isbn )
91
+ {
92
+ if (13 !== strlen ($ isbn ) || !ctype_digit ($ isbn )) {
93
+ return false;
94
+ }
95
+
96
+ $ checkSum = 0 ;
97
+
98
+ for ($ i = 0 ; $ i < 13 ; $ i += 2 ) {
99
+ $ checkSum += $ isbn {$ i };
87
100
}
101
+
102
+ for ($ i = 1 ; $ i < 12 ; $ i += 2 ) {
103
+ $ checkSum += $ isbn {$ i } * 3 ;
104
+ }
105
+
106
+ return 0 === $ checkSum % 10 ;
88
107
}
89
108
}
0 commit comments