Version 1
[yaffs-website] / vendor / symfony / validator / Constraints / IssnValidator.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Validator\Constraints;
13
14 use Symfony\Component\Validator\Context\ExecutionContextInterface;
15 use Symfony\Component\Validator\Constraint;
16 use Symfony\Component\Validator\ConstraintValidator;
17 use Symfony\Component\Validator\Exception\UnexpectedTypeException;
18
19 /**
20  * Validates whether the value is a valid ISSN.
21  *
22  * @author Antonio J. GarcĂ­a Lagar <aj@garcialagar.es>
23  * @author Bernhard Schussek <bschussek@gmail.com>
24  *
25  * @see https://en.wikipedia.org/wiki/Issn
26  */
27 class IssnValidator extends ConstraintValidator
28 {
29     /**
30      * {@inheritdoc}
31      */
32     public function validate($value, Constraint $constraint)
33     {
34         if (!$constraint instanceof Issn) {
35             throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Issn');
36         }
37
38         if (null === $value || '' === $value) {
39             return;
40         }
41
42         if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
43             throw new UnexpectedTypeException($value, 'string');
44         }
45
46         $value = (string) $value;
47         $canonical = $value;
48
49         // 1234-567X
50         //     ^
51         if (isset($canonical[4]) && '-' === $canonical[4]) {
52             // remove hyphen
53             $canonical = substr($canonical, 0, 4).substr($canonical, 5);
54         } elseif ($constraint->requireHyphen) {
55             if ($this->context instanceof ExecutionContextInterface) {
56                 $this->context->buildViolation($constraint->message)
57                     ->setParameter('{{ value }}', $this->formatValue($value))
58                     ->setCode(Issn::MISSING_HYPHEN_ERROR)
59                     ->addViolation();
60             } else {
61                 $this->buildViolation($constraint->message)
62                     ->setParameter('{{ value }}', $this->formatValue($value))
63                     ->setCode(Issn::MISSING_HYPHEN_ERROR)
64                     ->addViolation();
65             }
66
67             return;
68         }
69
70         $length = strlen($canonical);
71
72         if ($length < 8) {
73             if ($this->context instanceof ExecutionContextInterface) {
74                 $this->context->buildViolation($constraint->message)
75                     ->setParameter('{{ value }}', $this->formatValue($value))
76                     ->setCode(Issn::TOO_SHORT_ERROR)
77                     ->addViolation();
78             } else {
79                 $this->buildViolation($constraint->message)
80                     ->setParameter('{{ value }}', $this->formatValue($value))
81                     ->setCode(Issn::TOO_SHORT_ERROR)
82                     ->addViolation();
83             }
84
85             return;
86         }
87
88         if ($length > 8) {
89             if ($this->context instanceof ExecutionContextInterface) {
90                 $this->context->buildViolation($constraint->message)
91                     ->setParameter('{{ value }}', $this->formatValue($value))
92                     ->setCode(Issn::TOO_LONG_ERROR)
93                     ->addViolation();
94             } else {
95                 $this->buildViolation($constraint->message)
96                     ->setParameter('{{ value }}', $this->formatValue($value))
97                     ->setCode(Issn::TOO_LONG_ERROR)
98                     ->addViolation();
99             }
100
101             return;
102         }
103
104         // 1234567X
105         // ^^^^^^^ digits only
106         if (!ctype_digit(substr($canonical, 0, 7))) {
107             if ($this->context instanceof ExecutionContextInterface) {
108                 $this->context->buildViolation($constraint->message)
109                     ->setParameter('{{ value }}', $this->formatValue($value))
110                     ->setCode(Issn::INVALID_CHARACTERS_ERROR)
111                     ->addViolation();
112             } else {
113                 $this->buildViolation($constraint->message)
114                     ->setParameter('{{ value }}', $this->formatValue($value))
115                     ->setCode(Issn::INVALID_CHARACTERS_ERROR)
116                     ->addViolation();
117             }
118
119             return;
120         }
121
122         // 1234567X
123         //        ^ digit, x or X
124         if (!ctype_digit($canonical[7]) && 'x' !== $canonical[7] && 'X' !== $canonical[7]) {
125             if ($this->context instanceof ExecutionContextInterface) {
126                 $this->context->buildViolation($constraint->message)
127                     ->setParameter('{{ value }}', $this->formatValue($value))
128                     ->setCode(Issn::INVALID_CHARACTERS_ERROR)
129                     ->addViolation();
130             } else {
131                 $this->buildViolation($constraint->message)
132                     ->setParameter('{{ value }}', $this->formatValue($value))
133                     ->setCode(Issn::INVALID_CHARACTERS_ERROR)
134                     ->addViolation();
135             }
136
137             return;
138         }
139
140         // 1234567X
141         //        ^ case-sensitive?
142         if ($constraint->caseSensitive && 'x' === $canonical[7]) {
143             if ($this->context instanceof ExecutionContextInterface) {
144                 $this->context->buildViolation($constraint->message)
145                     ->setParameter('{{ value }}', $this->formatValue($value))
146                     ->setCode(Issn::INVALID_CASE_ERROR)
147                     ->addViolation();
148             } else {
149                 $this->buildViolation($constraint->message)
150                     ->setParameter('{{ value }}', $this->formatValue($value))
151                     ->setCode(Issn::INVALID_CASE_ERROR)
152                     ->addViolation();
153             }
154
155             return;
156         }
157
158         // Calculate a checksum. "X" equals 10.
159         $checkSum = 'X' === $canonical[7]
160         || 'x' === $canonical[7]
161         ? 10
162             : $canonical[7];
163
164         for ($i = 0; $i < 7; ++$i) {
165             // Multiply the first digit by 8, the second by 7, etc.
166             $checkSum += (8 - $i) * $canonical[$i];
167         }
168
169         if (0 !== $checkSum % 11) {
170             if ($this->context instanceof ExecutionContextInterface) {
171                 $this->context->buildViolation($constraint->message)
172                     ->setParameter('{{ value }}', $this->formatValue($value))
173                     ->setCode(Issn::CHECKSUM_FAILED_ERROR)
174                     ->addViolation();
175             } else {
176                 $this->buildViolation($constraint->message)
177                     ->setParameter('{{ value }}', $this->formatValue($value))
178                     ->setCode(Issn::CHECKSUM_FAILED_ERROR)
179                     ->addViolation();
180             }
181         }
182     }
183 }