1
0
Fork 0
mirror of https://github.com/Yetangitu/owncloud-apps.git synced 2025-10-02 14:49:17 +02:00
nextcloud-apps/files_opds/lib/isbn.php

181 lines
4.7 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* ownCloud - Files_Opds App
*
* @author Frank de Lange
* @copyright 2014 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Files_Opds;
/**
* ISBN class for OPDS
*/
class Isbn
{
const SUCCESS = 0;
const REQUEST_LIMIT_EXCEEDED = -1;
const NOT_FOUND = -2;
const ERROR = -3;
const RESCAN_LIMIT_EXCEEDED = 86400;
const RESCAN_NOT_FOUND = 604800;
const RESCAN_ERROR = 86400;
/**
* @brief try to find a valid ISBN in the given text, using a cascade of
* regexps.
*
* @param string $text text to search through
* @return string $hit ISBN on success, false otherwise
*/
public static function scan($text) {
$match = array();
foreach($text as $line) {
/* generic ISBN 10/13 pattern. Checks for unicode dashes ('‒–—―‑‐﹣--') as well as regular hyphens. */
if(preg_match_all('/ISBN(?:[ ‒–—―‑‐﹣--]?(?:1[03])?)?:?\s*(?=[\d Xx—―-]{10,17})(((?:97[89])[\d ‒–—―‑‐﹣--]{9,14})|([\d ‒–—―‑‐﹣--]{9,12}[\dXx]))/u', $line, $match)) {
foreach($match[1] as $hit) {
$hit = preg_replace('/[^0-9X]/i','',$hit);
if(self::validate($hit)) {
return $hit;
}
}
}
}
/* If nothing found, try prefix-less versions. Even though ISBN numbers should be
* presented with a 'ISBN' prefix, some publications omit this. These patterns
* are liable to generate false positives, so they should only be run after the
* prefixed version has exhausted the search without returning results.
*/
foreach($text as $line) {
/* prefix-less ISBN-13 targeted pattern */
if(preg_match_all('/(97[89][\d ‒–—―‑‐﹣--]\d{9,13}\d)/u',$line,$match)) {
foreach($match[1] as $hit) {
$hit = preg_replace('/[^0-9]/','',$hit);
if(self::validate($hit)) {
return $hit;
}
}
}
/* single ISBN-10 targeted pattern */
if(preg_match_all('/(\d[\d ‒–—―‑‐﹣--]{8,11}[\dXx])/u',$line,$match)) {
foreach($match[1] as $hit) {
$hit = preg_replace('/[^0-9X]/i','',$hit);
if(self::validate($hit)) {
return $hit;
}
}
}
}
/* No ISBN found */
return false;
}
/**
* @brief get metadata for given ISBN
*
* @param string $isbn ISBN to use
* @param arrayref &$meta OPDS metadata
* @return bool $success (true if metadata found)
*/
public static function get($isbn,&$meta) {
/* set ISBN in metadata; can be overwritten later with ISBN13 */
$meta['isbn'] = $isbn;
/* try Google first, then ISBNdb */
if (!(Isbn::SUCCESS == Google::get($isbn,$meta)) && (!(Isbn::SUCCESS == Isbndb::get($isbn,$meta)) )) {
/* Try ISBNdb, then Google */
//if (!(Isbn::SUCCESS == Isbndb::get($isbn,$meta)) && (!(Isbn::SUCCESS == Google::get($isbn,$meta)))) {
return false;
} else {
return true;
}
}
/**
* @brief validate ISBN
*
* @param string $isbn ISBN to validate
* @return bool true if ISBN is valid
*/
public static function validate($isbn) {
if (null === $isbn || '' === $isbn) {
return false;
}
switch (strlen($isbn)) {
case 10:
return self::isIsbn10($isbn);
break;
case 13:
return self::isIsbn13($isbn);
break;
}
return false;
}
/**
* @brief check for valid ISBN10
* @param string $isbn ISBN to check
* @return bool true if valid ISBN-10
*/
static function isIsbn10 ($isbn) {
$len = strlen($isbn);
if ($len == 10) {
//Calculate check digit
$check = 0;
for ($i = 0; $i < 9; $i++) {
if ($isbn[$i] === "X") {
$check += 10 * intval(10 - $i);
} else {
$check += intval($isbn[$i]) * intval(10 - $i);
}
}
$check = 11 - $check % 11;
if ($check === 10) {
$check = 'X';
} elseif ($check === 11) {
$check = 0;
}
return ($check == $isbn{$len - 1});
}
return false;
}
/**
* @brief check for valid ISBN13
* @param string $isbn ISBN to check
* @return bool true if valid ISBN-13
*/
static function isIsbn13 ($isbn) {
$len = strlen($isbn);
if ($len == 13) {
//Calculate check digit
$check = 0;
for ($i = 0; $i < 12; $i += 2) {
$check += substr($isbn, $i, 1);
}
for ($i = 1; $i < 12; $i += 2) {
$check += 3 * substr($isbn, $i, 1);
}
$check = 10 - $check % 10;
if ($check === 10) {
$check = 0;
}
return ($check == $isbn{$len - 1});
}
return false;
}
}