File indexing completed on 2024-12-22 05:37:12
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Validate 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * @see Zend_Validate_Abstract 0024 */ 0025 // require_once 'Zend/Validate/Abstract.php'; 0026 0027 /** 0028 * @category Zend 0029 * @package Zend_Validate 0030 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0031 * @license http://framework.zend.com/license/new-bsd New BSD License 0032 */ 0033 class Zend_Validate_Isbn extends Zend_Validate_Abstract 0034 { 0035 const AUTO = 'auto'; 0036 const ISBN10 = '10'; 0037 const ISBN13 = '13'; 0038 const INVALID = 'isbnInvalid'; 0039 const NO_ISBN = 'isbnNoIsbn'; 0040 0041 /** 0042 * Validation failure message template definitions. 0043 * 0044 * @var array 0045 */ 0046 protected $_messageTemplates = array( 0047 self::INVALID => "Invalid type given. String or integer expected", 0048 self::NO_ISBN => "'%value%' is not a valid ISBN number", 0049 ); 0050 0051 /** 0052 * Allowed type. 0053 * 0054 * @var string 0055 */ 0056 protected $_type = self::AUTO; 0057 0058 /** 0059 * Separator character. 0060 * 0061 * @var string 0062 */ 0063 protected $_separator = ''; 0064 0065 /** 0066 * Set up options. 0067 * 0068 * @param Zend_Config|array $options 0069 * @throws Zend_Validate_Exception When $options is not valid 0070 */ 0071 public function __construct($options = array()) 0072 { 0073 // prepare options 0074 if ($options instanceof Zend_Config) { 0075 $options = $options->toArray(); 0076 } 0077 if (!is_array($options)) { 0078 /** 0079 * @see Zend_Validate_Exception 0080 */ 0081 // require_once 'Zend/Validate/Exception.php'; 0082 throw new Zend_Validate_Exception('Invalid options provided.'); 0083 } 0084 0085 // set type 0086 if (array_key_exists('type', $options)) { 0087 $this->setType($options['type']); 0088 } 0089 0090 // set separator 0091 if (array_key_exists('separator', $options)) { 0092 $this->setSeparator($options['separator']); 0093 } 0094 } 0095 0096 /** 0097 * Detect input format. 0098 * 0099 * @return string 0100 */ 0101 protected function _detectFormat() 0102 { 0103 // prepare separator and pattern list 0104 $sep = quotemeta($this->_separator); 0105 $patterns = array(); 0106 $lengths = array(); 0107 0108 // check for ISBN-10 0109 if ($this->_type == self::ISBN10 || $this->_type == self::AUTO) { 0110 if (empty($sep)) { 0111 $pattern = '/^[0-9]{9}[0-9X]{1}$/'; 0112 $length = 10; 0113 } else { 0114 $pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/"; 0115 $length = 13; 0116 } 0117 0118 $patterns[$pattern] = self::ISBN10; 0119 $lengths[$pattern] = $length; 0120 } 0121 0122 // check for ISBN-13 0123 if ($this->_type == self::ISBN13 || $this->_type == self::AUTO) { 0124 if (empty($sep)) { 0125 $pattern = '/^[0-9]{13}$/'; 0126 $length = 13; 0127 } else { 0128 $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}$/"; 0129 $length = 17; 0130 } 0131 0132 $patterns[$pattern] = self::ISBN13; 0133 $lengths[$pattern] = $length; 0134 } 0135 0136 // check pattern list 0137 foreach ($patterns as $pattern => $type) { 0138 if ((strlen($this->_value) == $lengths[$pattern]) && preg_match($pattern, $this->_value)) { 0139 return $type; 0140 } 0141 } 0142 0143 return null; 0144 } 0145 0146 /** 0147 * Defined by Zend_Validate_Interface. 0148 * 0149 * Returns true if and only if $value is a valid ISBN. 0150 * 0151 * @param string $value 0152 * @return boolean 0153 */ 0154 public function isValid($value) 0155 { 0156 if (!is_string($value) && !is_int($value)) { 0157 $this->_error(self::INVALID); 0158 return false; 0159 } 0160 0161 $value = (string) $value; 0162 $this->_setValue($value); 0163 0164 switch ($this->_detectFormat()) { 0165 case self::ISBN10: 0166 // sum 0167 $isbn10 = str_replace($this->_separator, '', $value); 0168 $sum = 0; 0169 for ($i = 0; $i < 9; $i++) { 0170 $sum += (10 - $i) * $isbn10{$i}; 0171 } 0172 0173 // checksum 0174 $checksum = 11 - ($sum % 11); 0175 if ($checksum == 11) { 0176 $checksum = '0'; 0177 } elseif ($checksum == 10) { 0178 $checksum = 'X'; 0179 } 0180 break; 0181 0182 case self::ISBN13: 0183 // sum 0184 $isbn13 = str_replace($this->_separator, '', $value); 0185 $sum = 0; 0186 for ($i = 0; $i < 12; $i++) { 0187 if ($i % 2 == 0) { 0188 $sum += $isbn13{$i}; 0189 } else { 0190 $sum += 3 * $isbn13{$i}; 0191 } 0192 } 0193 // checksum 0194 $checksum = 10 - ($sum % 10); 0195 if ($checksum == 10) { 0196 $checksum = '0'; 0197 } 0198 break; 0199 0200 default: 0201 $this->_error(self::NO_ISBN); 0202 return false; 0203 } 0204 0205 // validate 0206 if (substr($this->_value, -1) != $checksum) { 0207 $this->_error(self::NO_ISBN); 0208 return false; 0209 } 0210 return true; 0211 } 0212 0213 /** 0214 * Set separator characters. 0215 * 0216 * It is allowed only empty string, hyphen and space. 0217 * 0218 * @param string $separator 0219 * @throws Zend_Validate_Exception When $separator is not valid 0220 * @return Zend_Validate_Isbn Provides a fluent interface 0221 */ 0222 public function setSeparator($separator) 0223 { 0224 // check separator 0225 if (!in_array($separator, array('-', ' ', ''))) { 0226 /** 0227 * @see Zend_Validate_Exception 0228 */ 0229 // require_once 'Zend/Validate/Exception.php'; 0230 throw new Zend_Validate_Exception('Invalid ISBN separator.'); 0231 } 0232 0233 $this->_separator = $separator; 0234 return $this; 0235 } 0236 0237 /** 0238 * Get separator characters. 0239 * 0240 * @return string 0241 */ 0242 public function getSeparator() 0243 { 0244 return $this->_separator; 0245 } 0246 0247 /** 0248 * Set allowed ISBN type. 0249 * 0250 * @param string $type 0251 * @throws Zend_Validate_Exception When $type is not valid 0252 * @return Zend_Validate_Isbn Provides a fluent interface 0253 */ 0254 public function setType($type) 0255 { 0256 // check type 0257 if (!in_array($type, array(self::AUTO, self::ISBN10, self::ISBN13))) { 0258 /** 0259 * @see Zend_Validate_Exception 0260 */ 0261 // require_once 'Zend/Validate/Exception.php'; 0262 throw new Zend_Validate_Exception('Invalid ISBN type'); 0263 } 0264 0265 $this->_type = $type; 0266 return $this; 0267 } 0268 0269 /** 0270 * Get allowed ISBN type. 0271 * 0272 * @return string 0273 */ 0274 public function getType() 0275 { 0276 return $this->_type; 0277 } 0278 }