You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
12 KiB
PHP

<?php
require_once('DbMapping.php');
class BookNotFoundException extends WebException {
public function __construct($code) {
parent::__construct('BookNotFound', "The book with code $code was not found", -404);
}
}
function convertMSChar($src)
{
$text = preg_replace('/([\xc0-\xdf].)/se', "'&#' . ((ord(substr('$1', 0, 1)) - 192) * 64 + (ord(substr('$1', 1, 1)) - 128)) . ';'", $src);
$text = preg_replace('/([\xe0-\xef]..)/se', "'&#' . ((ord(substr('$1', 0, 1)) - 224) * 4096 + (ord(substr('$1', 1, 1)) - 128) * 64 + (ord(substr('$1', 2, 1)) - 128)) . ';'", $text);
return $text;
}
/**
* AudioBook is mapped on a Notice from NetBiblio
*
* @property string id
* @property string sql_id
* @property string title
* @property string sql_title
* @property string author
* @property string sql_author
* @property string code
* @property string sql_code
* @property string summary
* @property string sql_summary
* @property string editor
* @property string sql_editor
* @property string media
* @property string sql_media
* @property string collection
* @property string sql_collection
* @property string isbn
* @property string sql_isbn
* @property string readBy
* @property string sql_readBy
* @property string cover
* @property string sql_cover
* @property string category
* @property string sql_category
* @property string date
* @property string sql_date
* @property string code3
* @property string sql_code3
* @property string code3Long
* @property string sql_code3Long
* @property string genre
* @property string sql_genre
* @property string genreCode
* @property string sql_genreCode
* @property string coverdisplay
* @property string sql_coverdisplay
* @property string link
* @property string sql_link
* @property string linkTitle
* @property string sql_linkTitle
* @property string typeMedia1
* @property string sql_typeMedia1
*/
class AudioBook extends DbMapping
{
protected $attributeNames = 'id title author code summary editor media collection isbn readBy cover category date code3 code3Long genre genreCode coverdisplay link linkTitle typeMedia1';
public static function find($id) {
return self::findBy('NoticeID', $id);
}
/**
* If $id is an array, return an array of book, if it is only one id, return one book
* Load books details only if not an array.
*
* Beware that this search use the NoticeID, not the NoticeNr, if you need the last one
* use findByCode method instead;
*
* @param string $column
* @param int|array $ids
* @param bool $raw results ?
* @return AudioBook|AudioBook[]|array
*/
public static function findBy($column, $ids, $raw = false)
{
$multiple = true;
if(! is_array($ids)) {
$ids = array($ids);
$multiple = false;
}
$sql = sprintf("SELECT DISTINCT
Notices.[NoticeID] AS id,
Notices.[Title] AS title,
Notices.[Author] AS author,
LTRIM(RTRIM(Notices.[NoticeNr])) AS code,
Fields.[520] AS summary,
Fields.[260b] + ' ' + Fields.[260c] AS editor,
Fields.[300] AS media,
Fields.[490a] AS collection,
isbn.DisplayText AS isbn,
Fields.[901] AS readBy,
Fields.[899a] AS cover,
'' AS category, -- supposed to come from tags 600, 610, 650, 651, 655, 690, 691, 695, 696 but always empty anyway
CONVERT(VARCHAR, Notices.[CreationDate], 102) AS date,
LTRIM(RTRIM(Notices.[userdefined3code])) AS code3,
[Code3].TextFre AS code3Long,
[GenreCode].TextFre AS genre,
[GenreCode].Code AS genreCode,
Notices.[coverdisplay],
Fields.[856u] AS link,
Fields.[856z] AS linkTitle,
Notices.[MediaType1Code] AS typeMedia1
FROM Notices
INNER JOIN Codes AS Code3 ON Notices.userdefined3code = Code3.Code AND Code3.Type=6
INNER JOIN Codes AS GenreCode ON MediaType2Code = GenreCode.Code AND GenreCode.Type = 2
LEFT OUTER JOIN (
SELECT *
FROM (
SELECT
NoticeID,
CASE
WHEN Tag IN ('490', '260', '856', '899') THEN Tag + SubfieldCode
ELSE Tag
END AS Field,
CASE
WHEN Tag = '020' THEN CAST(AuthorityID AS varchar)
ELSE ContentShortPart
END AS Data
FROM NoticeFields
WHERE
Tag IN (
'520', -- summary
'901', -- Reader
'300', -- Duration (field media)
'020' -- ISBN
)
OR (Tag = '490' AND SubfieldCode = 'a') -- Collection
OR (Tag = '260' AND SubfieldCode = 'b') -- Editor
OR (Tag = '260' AND SubfieldCode = 'c') -- Edition year
OR (Tag = '856' AND SubfieldCode = 'u') -- Link
OR (Tag = '856' AND SubfieldCode = 'z') -- Link title
OR (Tag = '899' AND SubfieldCode = 'a') -- Cover
) AS src
PIVOT (
MIN(Data)
FOR Field IN ([520], [901], [300], [020], [490a], [260b], [260c], [856u], [856z], [899a])
) AS pvt
) Fields ON Notices.NoticeID = Fields.NoticeID
LEFT JOIN Authorities AS isbn ON isbn.AuthorityID = Fields.[020]
WHERE
LTRIM(RTRIM(Notices.[%s])) IN ('%s')
AND Notices.[NoticeNr] NOT LIKE '%%~%%'
;", $column, implode('\', \'', $ids));
$result = Connection::execute($sql, true);
$books = array();
while($row = $result->next()) {
if($row['coverdisplay'] == 2) {
$row['cover'] = 'http://fichiers.bibliothequesonore.ch:8089/netbiblio/images/covers/Cover'.$row['id'].'_Original.jpg';
} else if(strlen($row['cover']) > 0) {
$row['cover'] = 'http://ecx.images-amazon.com/images/I/'.$row['cover'].'._SL320_.jpg';
}
$books[$row['id']] = $raw ? $row : new AudioBook($row);
}
return $multiple ? $books : reset($books);
}
/**
* @param $code
* @return int
* @throws BookNotFoundException
* @throws SqlException
*/
public static function findIdByCode($code)
{
$sql = "SELECT NoticeId FROM Notices WHERE LTRIM(RTRIM(NoticeNr)) = '$code';";
$result = Connection::execute($sql, false);
if ($result === false || $result->length == 0) {
throw new BookNotFoundException($code);
}
$row = $result->current();
return $row['NoticeId'];
}
/**
* Retrieve the list of all readers (volunteers) having read at least 4 books (2 notices per book).
* Returns an associative array containing $lastname and $firstname
*/
public static function listOfReaders()
{
$sql = "SELECT
count(*),
ContentShortPart AS name
FROM NoticeFields
WHERE Tag=901
GROUP BY ContentShortPart
HAVING count(*) > 6
ORDER BY SUBSTRING(ContentShortPart, CHARINDEX(' ', ContentShortPart)+1, 15);";
$results = Connection::execute($sql);
return array_map(function($row) {
$fullname = str_replace("*", "", $row['name']);
$parts = explode(" ", $fullname);
$firstname = array_shift($parts);
$lastname = implode(" ", $parts);
return array(
'lastname' => $lastname,
'firstname' => $firstname);
}, $results->to_array());
}
/**
* Retrieve the list of all categories
*/
public static function listOfCategories()
{
$sql = "SELECT
LTRIM(RTRIM(Code)) as code,
TextFre AS text
FROM Codes
WHERE
type=2
AND Code!='-'
ORDER BY TextFre;";
$results = Connection::execute($sql);
return array_map(function($row) {
return array(
'code' => $row['code'],
'text' => $row['text'],
);
}, $results->to_array());
}
/**
* Retrieve the list of all type available in the database.
*/
public static function listOfTypes()
{
$sql = "SELECT DISTINCT
Codes.TextFre AS type
FROM Codes
INNER JOIN Notices ON Codes.Code = Notices.MediaType2Code
WHERE
Codes.Type = 2
AND Notices.NoticeNr NOT LIKE '%~%'
AND Notices.NoticeNr NOT LIKE '%V%'
AND Notices.NoticeNr NOT LIKE '%T%'
AND Notices.MediaType1Code = 'CDD';";
$results = Connection::execute($sql);
$results = array_map(function($r) {
return $r['type'];
}, $results->to_array());
array_unshift($results, "Jeunesse");
return $results;
}
/**
* Retrieve the list of all books currently lended to readers.
*/
public static function inReading()
{
$sql = "SELECT
noticenr, title, author, displayName
FROM notices, items, circulations, useraccounts
WHERE
mediatype1code='N' and NoticeNr not like '%~%'
AND items.noticeid = notices.noticeid
AND items.ItemID=circulations.ItemID
AND useraccounts.useraccountid=circulations.useraccountid
ORDER BY author, title;";
$results = Connection::execute($sql);
return array_map(function($row) {
return array(
"noticenr" => $row['noticenr'],
"auteur" => $row['author'],
"titre" => $row['title'],
"lecteur" => $row['displayName']
);
}, $results->to_array());
}
public function __set($name, $value)
{
if ($name == 'code' && is_string($value)) {
$value = preg_replace('/[~a-zA-Z]/', '', $value);
}
parent::__set($name, $value);
}
}