|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Created on: <17-Apr-2007 11:07:06 bjorn> 00004 // 00005 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00006 // SOFTWARE NAME: eZ Publish 00007 // SOFTWARE RELEASE: 4.0.x 00008 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00009 // SOFTWARE LICENSE: GNU General Public License v2.0 00010 // NOTICE: > 00011 // This program is free software; you can redistribute it and/or 00012 // modify it under the terms of version 2.0 of the GNU General 00013 // Public License as published by the Free Software Foundation. 00014 // 00015 // This program is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU General Public License for more details. 00019 // 00020 // You should have received a copy of version 2.0 of the GNU General 00021 // Public License along with this program; if not, write to the Free 00022 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00023 // MA 02110-1301, USA. 00024 // 00025 // 00026 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00027 // 00028 00029 /*! \file ezisbn13.php 00030 */ 00031 00032 /*! 00033 \class eZISBN13 ezisbn13.php 00034 \brief The class eZISBN13 handles ISBN-13 numbers. 00035 00036 The class is containing an ISBN-13 number and extracts the different groups 00037 based on the information stored in the different ranges for Registration group 00038 and Registration elements. The Publication element will get the space left available. 00039 */ 00040 00041 //include_once( 'kernel/classes/datatypes/ezisbn/ezisbngroup.php' ); 00042 //include_once( 'kernel/classes/datatypes/ezisbn/ezisbngrouprange.php' ); 00043 //include_once( 'kernel/classes/datatypes/ezisbn/ezisbnregistrantrange.php' ); 00044 00045 class eZISBN13 00046 { 00047 const PREFIX_LENGTH = 3; 00048 const CHECK_LENGTH = 1; 00049 const LENGTH = 13; 00050 const PREFIX_978 = 978; 00051 const PREFIX_979 = 979; 00052 00053 /*! 00054 Constructor 00055 \param $isbnNr is the ISBN-13 number. example is: 978-0-11-000222-4 00056 \param $separator is the hyphen used in the ISBN number to make the 00057 ISBN number more visible. 00058 */ 00059 function eZISBN13( $isbnNr = null, $separator = '-' ) 00060 { 00061 if ( $isbnNr !== null ) 00062 { 00063 $this->extractISBNNumber( $isbnNr, $separator ); 00064 } 00065 else 00066 { 00067 $this->Prefix = false; 00068 $this->RegistrationGroup = false; 00069 $this->RegistrantElement = false; 00070 $this->PublicationElement = false; 00071 $this->CheckDigit = false; 00072 } 00073 } 00074 00075 /*! 00076 Contains a list of all attributes for this class. 00077 \return the array with existing attributes. 00078 */ 00079 function attributes() 00080 { 00081 return array( 'has_content', 00082 'group_ranges', 00083 'groups' ); 00084 } 00085 00086 /*! 00087 Fetch the attribute sent in $value. 00088 \param $value is the name of the attribute that should be fetched. 00089 \return the result of the attribute. 00090 */ 00091 function attribute( $value ) 00092 { 00093 switch ( $value ) 00094 { 00095 case "has_content": 00096 { 00097 return eZISBN13::hasRangeData(); 00098 }break; 00099 00100 case "groups": 00101 { 00102 $groupList = eZISBNGroup::fetchList(); 00103 return array( 'group_list' => $groupList, 00104 'count' => count( $groupList ) ); 00105 }break; 00106 00107 case "group_ranges": 00108 { 00109 $groupList = eZISBNGroupRange::fetchList(); 00110 return array( 'group_list' => $groupList, 00111 'count' => count( $groupList ) ); 00112 }break; 00113 } 00114 return null; 00115 } 00116 00117 /*! 00118 Check if the attribute set in the string $value exists. 00119 \param $value is the attribute you want to see if exist. 00120 \return true if the attribute is found. 00121 */ 00122 function hasAttribute( $value ) 00123 { 00124 return in_array( $value, eZISBN13::attributes() ); 00125 } 00126 00127 /*! 00128 Check if any ISBN ranges exist. 00129 \return true if any ranges are found. 00130 */ 00131 function hasRangeData() 00132 { 00133 $db = eZDB::instance(); 00134 $tableList = $db->eZTableList(); 00135 if ( array_key_exists( 'ezisbn_group', $tableList ) and 00136 array_key_exists( 'ezisbn_group_range', $tableList ) and 00137 array_key_exists( 'ezisbn_registrant_range', $tableList ) ) 00138 { 00139 $query = "SELECT count( ezisbn_group.id ) AS count 00140 FROM ezisbn_group, ezisbn_group_range, ezisbn_registrant_range 00141 WHERE ezisbn_group.group_number >= ezisbn_group_range.from_number AND 00142 ezisbn_group.group_number <= ezisbn_group_range.to_number AND 00143 ezisbn_group.id=ezisbn_registrant_range.isbn_group_id"; 00144 $countArray = $db->arrayQuery( $query ); 00145 return ( $countArray[0]['count'] > 0 ); 00146 } 00147 else 00148 return false; 00149 } 00150 00151 /*! 00152 Receives an ISBN number and place hyphen on the correct place in the number. 00153 If the placement is not found, an error message will be set and false 00154 00155 The different parts of the ISBN-13 number will be stored in separate class variables. 00156 00157 \param $isbnNr is the ISBN-13 number. Should be 13 digits long and may contain space or hyphen as separator. 00158 \param $error is used to send back an error message that will be shown to the user if the ISBN number was 00159 not extracted correctly. 00160 \param $separator is the separator used to make the ISBN number visible. Could be either a space or hyphen. 00161 \return A formated ISBN number or the original value if it was not possible to find the structure. 00162 */ 00163 function formatedISBNValue( $isbnNr = false, &$error, $separator = '-' ) 00164 { 00165 if ( $isbnNr !== false ) 00166 { 00167 $formatedISBN13 = preg_replace( "/[\s|\-]+/", "-", $isbnNr ); 00168 $status = $this->extractISBNNumber( $isbnNr, $error ); 00169 00170 if ( $status === false ) 00171 { 00172 $formatedISBN13 = substr( $isbnNr, 0, self::PREFIX_LENGTH ); 00173 if ( strlen( $this->RegistrationGroup ) > 0 ) 00174 { 00175 $formatedISBN13 .= $separator . $this->RegistrationGroup; 00176 if ( strlen( $this->RegistrantElement ) > 0 ) 00177 { 00178 $formatedISBN13 .= $separator . $this->RegistrantElement . $separator . 00179 $this->PublicationElement . $separator; 00180 } 00181 else 00182 { 00183 $offset = strlen( $this->RegistrationGroup ) + self::PREFIX_LENGTH; 00184 $length = strlen( $isbnNr ) - $offset - self::CHECK_LENGTH; 00185 $originalValue = substr( $isbnNr, $offset, $length ); 00186 $formatedISBN13 .= $originalValue; 00187 } 00188 } 00189 else 00190 { 00191 $offset = self::PREFIX_LENGTH; 00192 $length = strlen( $isbnNr ) - $offset - self::CHECK_LENGTH; 00193 $originalValue = substr( $isbnNr, $offset, $length ); 00194 $formatedISBN13 .= $originalValue; 00195 } 00196 00197 $length = strlen( $isbnNr ); 00198 $formatedISBN13 .= substr( $isbnNr, $length - self::CHECK_LENGTH, $length ); 00199 return $formatedISBN13; 00200 } 00201 } 00202 else 00203 { 00204 $formatedISBN13 = $this->Prefix . $separator; 00205 if ( strlen( $this->RegistrationGroup ) > 0 ) 00206 { 00207 $formatedISBN13 .= $this->RegistrationGroup . $separator; 00208 if ( strlen( $this->RegistrantElement ) > 0 ) 00209 { 00210 $formatedISBN13 .= $this->RegistrantElement . $separator . 00211 $this->PublicationElement . $separator; 00212 } 00213 else 00214 { 00215 $formatedISBN13 .= $this->RegistrantElement . 00216 $this->PublicationElement . $separator; 00217 } 00218 } 00219 else 00220 { 00221 $formatedISBN13 .= $this->RegistrationGroup . 00222 $this->RegistrantElement . 00223 $this->PublicationElement . $separator; 00224 } 00225 $formatedISBN13 .= $this->CheckDigit; 00226 } 00227 00228 if ( strlen( $this->Prefix . $this->RegistrationGroup . $this->RegistrantElement . $this->PublicationElement . $this->CheckDigit ) == self::LENGTH ) 00229 { 00230 $formatedISBN13 = $this->Prefix . $separator . 00231 $this->RegistrationGroup . $separator . 00232 $this->RegistrantElement . $separator . 00233 $this->PublicationElement . $separator . 00234 $this->CheckDigit; 00235 } 00236 return $formatedISBN13; 00237 } 00238 00239 /*! 00240 Extracts the ISBN-13 number and are setting the class variables for the different 00241 parts when the value is found. The class variables should be set as default false 00242 in the constructor. 00243 00244 \param $isbnNr is the ISBN-13 number. Should be 13 digits long and may contain space or hyphen as separator. 00245 \param $error is used to send back an error message that will be shown to the user if the ISBN number was 00246 not extracted correctly. 00247 00248 \return true if the ISBN-13 number was successfully extracted and false if not. 00249 */ 00250 function extractISBNNumber( $isbnNr = false, &$error ) 00251 { 00252 $ini = eZINI::instance( 'content.ini' ); 00253 $ean = preg_replace( "/[\s|\-]+/", "", $isbnNr ); 00254 if ( is_numeric( $ean ) and strlen( $ean ) == self::LENGTH ) 00255 { 00256 $prefix = substr( $ean, 0, self::PREFIX_LENGTH ); 00257 $this->Prefix = $prefix; 00258 00259 $checkDigit = substr( $ean, 12, self::CHECK_LENGTH ); 00260 $this->CheckDigit = $checkDigit; 00261 if ( $prefix == self::PREFIX_978 ) 00262 { 00263 $registrantValue = false; 00264 $groupValue = false; 00265 $publicationValue = false; 00266 $checkDigit = false; 00267 00268 $groupRange = eZISBNGroupRange::extractGroup( $ean ); 00269 $groupLength = false; 00270 if ( $groupRange ) 00271 { 00272 $groupLength = $groupRange->attribute( 'group_length' ); 00273 } 00274 00275 if ( $groupLength ) 00276 { 00277 $groupValue = substr( $ean, self::PREFIX_LENGTH, $groupLength ); 00278 $this->RegistrationGroup = $groupValue; 00279 00280 $group = eZISBNGroup::fetchByGroup( $groupValue ); 00281 if ( $group instanceof eZISBNGroup ) 00282 { 00283 $registrant = eZISBNRegistrantRange::extractRegistrant( $ean, $group, $groupRange, $registrantLength ); 00284 if ( $registrant instanceof eZISBNRegistrantRange and 00285 $registrantLength > 0 ) 00286 { 00287 $registrantOffset = self::PREFIX_LENGTH + $groupLength; 00288 $registrantValue = substr( $ean, $registrantOffset, $registrantLength ); 00289 00290 $this->RegistrantElement = $registrantValue; 00291 00292 $publicationOffset = $registrantOffset + $registrantLength; 00293 $publicationLength = 12 - $publicationOffset; 00294 $publicationValue = substr( $ean, $publicationOffset, $publicationLength ); 00295 $this->PublicationElement = $publicationValue; 00296 } 00297 else 00298 { 00299 $strictValidation = $ini->variable( 'ISBNSettings', 'StrictValidation' ); 00300 if ( $strictValidation == 'true' ) 00301 { 00302 $error = ezi18n( 'kernel/classes/datatypes', 'The registrant element of the ISBN number does not exist.' ); 00303 return false; 00304 } 00305 } 00306 } 00307 else 00308 { 00309 $strictValidation = $ini->variable( 'ISBNSettings', 'StrictValidation' ); 00310 if ( $strictValidation == 'true' ) 00311 { 00312 $error = ezi18n( 'kernel/classes/datatypes', 'The ISBN number has a incorrect registration group number.' ); 00313 return false; 00314 } 00315 } 00316 } 00317 else 00318 { 00319 $strictValidation = $ini->variable( 'ISBNSettings', 'StrictValidation' ); 00320 if ( $strictValidation == 'true' ) 00321 { 00322 $error = ezi18n( 'kernel/classes/datatypes', 'The group element of the ISBN number does not exist.' ); 00323 return false; 00324 } 00325 } 00326 } 00327 else 00328 { 00329 $strictValidation = $ini->variable( 'ISBNSettings', 'StrictValidation' ); 00330 if ( $strictValidation == 'true' ) 00331 { 00332 $error = ezi18n( 'kernel/classes/datatypes', '%1 is not a valid prefix of the ISBN number.', null, array( $prefix ) ); 00333 return false; 00334 } 00335 } 00336 } 00337 else 00338 { 00339 $error = ezi18n( 'kernel/classes/datatypes', 'All ISBN 13 characters need to be numeric' ); 00340 return false; 00341 } 00342 return true; 00343 } 00344 00345 /*! 00346 Validates the ISBN-13 number \a $isbnNr. 00347 \param $isbnNr A string containing the number without any dashes. 00348 \param $error is used to send back an error message that will be shown to the user if the ISBN number was 00349 not extracted correctly. 00350 \return \c true if it is valid. 00351 */ 00352 function validate( $isbnNr, &$error ) 00353 { 00354 $valid = $this->validateISBN13Checksum( $isbnNr, $error ); 00355 if ( $valid == true ) 00356 { 00357 $valid = $this->extractISBNNumber( $isbnNr, $error ); 00358 } 00359 return $valid; 00360 } 00361 00362 /*! 00363 \private 00364 Validates the ISBN-13 number \a $isbnNr. 00365 \param $isbnNr A string containing the number without any dashes. 00366 \param $error is used to send back an error message that will be shown to the user if the 00367 ISBN number validated. 00368 \return \c true if it is valid. 00369 */ 00370 function validateISBN13Checksum ( $isbnNr, &$error ) 00371 { 00372 if ( !$isbnNr ) 00373 return false; 00374 $isbnNr = preg_replace( "/[\s|\-]+/", "", $isbnNr ); 00375 if ( substr( $isbnNr, 0, self::PREFIX_LENGTH ) != self::PREFIX_978 and 00376 substr( $isbnNr, 0, self::PREFIX_LENGTH ) != self::PREFIX_979 ) 00377 { 00378 $error = ezi18n( 'kernel/classes/datatypes', 00379 '13 digit ISBN must start with 978 or 979' ); 00380 return false; 00381 } 00382 00383 $checksum13 = 0; 00384 $weight13 = 1; 00385 if ( strlen( $isbnNr ) != self::LENGTH ) 00386 { 00387 $error = ezi18n( 'kernel/classes/datatypes', 'ISBN length is invalid' ); 00388 return false; 00389 } 00390 00391 //compute checksum 00392 $val = 0; 00393 for ( $i = 0; $i < self::LENGTH; $i++ ) 00394 { 00395 $val = $isbnNr{$i}; 00396 if ( !is_numeric( $isbnNr{$i} ) ) 00397 { 00398 $error = ezi18n( 'kernel/classes/datatypes', 'All ISBN 13 characters need to be numeric' ); 00399 return false; 00400 } 00401 $checksum13 = $checksum13 + $weight13 * $val; 00402 $weight13 = ( $weight13 + 2 ) % 4; 00403 } 00404 if ( ( $checksum13 % 10 ) != 0 ) 00405 { 00406 // Calculate the last digit from the 12 first numbers. 00407 $checkDigit = ( 10 - ( ( $checksum13 - ( ( $weight13 + 2 ) % 4 ) * $val ) % 10 ) ) % 10; 00408 //bad checksum 00409 $error = ezi18n( 'kernel/classes/datatypes', 'Bad checksum, last digit should be %1', null, array( $checkDigit ) ); 00410 return false; 00411 } 00412 00413 return true; 00414 } 00415 00416 public $Prefix; 00417 public $RegistrationGroup; 00418 public $RegistrantElement; 00419 public $PublicationElement; 00420 public $CheckDigit; 00421 } 00422 00423 ?>