3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Validator
;
12 class Isbn
extends AbstractValidator
17 const INVALID
= 'isbnInvalid';
18 const NO_ISBN
= 'isbnNoIsbn';
21 * Validation failure message template definitions.
25 protected $messageTemplates = array(
26 self
::INVALID
=> "Invalid type given. String or integer expected",
27 self
::NO_ISBN
=> "The input is not a valid ISBN number",
30 protected $options = array(
31 'type' => self
::AUTO
, // Allowed type
32 'separator' => '', // Separator character
36 * Detect input format.
40 protected function detectFormat()
42 // prepare separator and pattern list
43 $sep = quotemeta($this->getSeparator());
46 $type = $this->getType();
49 if ($type == self
::ISBN10 ||
$type == self
::AUTO
) {
51 $pattern = '/^[0-9]{9}[0-9X]{1}$/';
54 $pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/";
58 $patterns[$pattern] = self
::ISBN10
;
59 $lengths[$pattern] = $length;
63 if ($type == self
::ISBN13 ||
$type == self
::AUTO
) {
65 $pattern = '/^[0-9]{13}$/';
68 $pattern = "/^[0-9]{1,9}[{$sep}]{1}[0-9]{1,5}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1}$/";
72 $patterns[$pattern] = self
::ISBN13
;
73 $lengths[$pattern] = $length;
77 foreach ($patterns as $pattern => $type) {
78 if ((strlen($this->getValue()) == $lengths[$pattern]) && preg_match($pattern, $this->getValue())) {
87 * Returns true if and only if $value is a valid ISBN.
89 * @param string $value
92 public function isValid($value)
94 if (!is_string($value) && !is_int($value)) {
95 $this->error(self
::INVALID
);
99 $value = (string) $value;
100 $this->setValue($value);
102 switch ($this->detectFormat()) {
105 $isbn10 = str_replace($this->getSeparator(), '', $value);
107 for ($i = 0; $i < 9; $i++
) {
108 $sum +
= (10 - $i) * $isbn10{$i};
112 $checksum = 11 - ($sum %
11);
113 if ($checksum == 11) {
115 } elseif ($checksum == 10) {
122 $isbn13 = str_replace($this->getSeparator(), '', $value);
124 for ($i = 0; $i < 12; $i++
) {
128 $sum +
= 3 * $isbn13{$i};
132 $checksum = 10 - ($sum %
10);
133 if ($checksum == 10) {
139 $this->error(self
::NO_ISBN
);
144 if (substr($this->getValue(), -1) != $checksum) {
145 $this->error(self
::NO_ISBN
);
152 * Set separator characters.
154 * It is allowed only empty string, hyphen and space.
156 * @param string $separator
157 * @throws Exception\InvalidArgumentException When $separator is not valid
158 * @return Isbn Provides a fluent interface
160 public function setSeparator($separator)
163 if (!in_array($separator, array('-', ' ', ''))) {
164 throw new Exception\
InvalidArgumentException('Invalid ISBN separator.');
167 $this->options
['separator'] = $separator;
172 * Get separator characters.
176 public function getSeparator()
178 return $this->options
['separator'];
182 * Set allowed ISBN type.
184 * @param string $type
185 * @throws Exception\InvalidArgumentException When $type is not valid
186 * @return Isbn Provides a fluent interface
188 public function setType($type)
191 if (!in_array($type, array(self
::AUTO
, self
::ISBN10
, self
::ISBN13
))) {
192 throw new Exception\
InvalidArgumentException('Invalid ISBN type');
195 $this->options
['type'] = $type;
200 * Get allowed ISBN type.
204 public function getType()
206 return $this->options
['type'];