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.

443 lines
14 KiB
PHP

<?php
/*
* Copyright Mathieu Schroeter for the BSR, 2013
* Modif Simon Schulé pour la BSR, 2013. 2014
* Copyright Gilles Crettenand for the BSR, 2015
*/
require_once "global.php";
require_once "mobile.webservice.php";
require_once "lib/AudioBook.php";
require_once "lib/User.php";
require_once "lib/BookSearch.php";
class NetBiblio extends WebService
{
private $login = '';
private $client = 'website';
public function AddDownloadLog($client, $login, $code)
{
$client = str_replace("'", "", $client);
$login = str_replace("'", "", $login);
$code = ltrim(str_replace("'", "", $code), '0');
$itemNr = $code . 'V';
$sql = "SELECT itemID FROM Items WHERE LTRIM(RTRIM(ItemNr)) = '$itemNr';";
$result = Connection::execute($sql, false);
if ($row = $result->current()) {
$itemId = $row['itemID'];
} else {
throw new WebException("ItemNotFound", "cannot find item", -1030);
}
$sql = "SELECT UserAccountID FROM UserAccounts WHERE LTRIM(RTRIM(UserAccountNr)) = '$login';";
$result = Connection::execute($sql, false);
if ($row = $result->current()) {
$userId = $row['UserAccountID'];
} else {
throw new WebException("UserNotFound", "cannot find user", -1031);
}
$sql = "SELECT circulationId
FROM OldCirculations
WHERE
useraccountID= $userId AND
itemID = $itemId AND
LTRIM(RTRIM(remark)) = '$client';";
$result = Connection::execute($sql, false);
if ($row = $result->current()) {
$id = $row['circulationId'];
$sql = "UPDATE OldCirculations
SET
CheckInDate=GETDATE(),
CheckOutDate=GETDATE()
WHERE circulationID = $id";
Connection::execute($sql);
return true;
}
$sql = "SELECT TOP 1 circulationID FROM OldCirculations ORDER BY CirculationID DESC";
$result = Connection::execute($sql, false);
if ($row = $result->current()) {
$nextId = $row['circulationID'] + 1;
} else {
$nextId = 1;
}
$sql = "UPDATE Useraccounts
SET
Circulations = Circulations + 1,
TotalCirculations = TotalCirculations + 1
WHERE UseraccountID = $userId;";
Connection::execute($sql);
$sql = "UPDATE Items
SET
Circulations = Circulations + 1,
TotalCirculations = TotalCirculations + 1
WHERE ItemID = $itemId;";
Connection::execute($sql);
$worker_id = Configuration::get('netbiblio_worker_id');
$sql = "INSERT INTO OldCirculations (
CirculationID, ItemID, UseraccountID,
Remark,
DueDate, CheckOutDate, CheckInDate,
CheckOutBranchofficeID, CheckOutEmployeeID, CheckInBranchofficeID, CheckInEmployeeID,
Reminders, Renewals, Prereminder, InfoCode, CheckOutSIP2Info, CheckInSIP2Info
) VALUES (
$nextId, $itemId, $userId,
'$client',
DATEADD(month, 2, GETDATE()), GETDATE(), GETDATE(),
2, $worker_id, 2, $worker_id,
0, 0, 1, '-', 1, 1
);";
Connection::execute($sql);
return true;
}
public function Authenticate($login, $password, $client = "website")
{
session_unset(); /* destroy all session vars */
$user = User::authenticate($login, $password);
if (!$user) {
throw new WebException ("AuthenticateBad", "authentication failed", -100);
}
$_SESSION["user"]["login"] = $login;
$_SESSION["user"]["client"] = $client;
$this->login = $login;
$this->client = $client;
return $user->toArray();
}
public function Disconnect()
{
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]);
}
return array();
}
public function IsAuthenticated()
{
return $this->getUser()->toArray();
}
/**
* Adds entries to OldCirculations in Netbiblio database and increments counters on items and useraccounts tables
* For now, keeps a separate log in BSRDownload Database to store IPs
* In case a download has already been logged, only the date of the existing entry is updated, no counter incremented.
* @param string $login
* @return User
* @throws WebException in case the login cannot be found in the database
*/
private function getUser($login = null)
{
if (!$login) {
$login = $_SESSION["user"]["login"];
}
$this->checkSession($login);
$user = User::find($this->login);
if (!$user) {
throw new WebException ("UserNotFound", "cannot find account", -130);
}
return $user;
}
private function CheckSession($login = null, $client = null)
{
if (!isset ($_SESSION["user"]["login"])) {
return;
}
if(!$client) {
$client = isset($_SESSION["user"]["client"]) ? $_SESSION["user"]["client"] : 'website';
}
if (!$login) {
$login = $_SESSION["user"]["login"];
} else if ($_SESSION["user"]["login"] !== $login) {
throw new WebException ("CheckSessionBadAuth", "bad authentication", -1001);
}
$this->login = $login;
$this->client = $client;
}
public function FindAccount($login)
{
return $this->getUser($login)->toArray();
}
public function GetWishes()
{
$books = $this->getUser()->getWishes();
return array_values(array_map(array($this, 'AddFiles'), $books));
}
public function GetCirculations()
{
$circulations = $this->getUser()->getCirculations();
return array_values(array_map(array($this, 'AddFiles'), $circulations));
}
public function GetOldCirculations()
{
$circulations = $this->getUser()->getOldCirculations();
return array_values(array_map(array($this, 'AddFiles'), $circulations));
}
public function AddWish($bookNr)
{
return $this->getUser()->addWish($bookNr);
}
public function DeleteWish($bookNr)
{
$this->getUser()->deleteWish($bookNr);
}
public function FindBooks($codes)
{
$this->CheckSession();
$codes = json_decode($codes, true);
$codes = array_map('intval', $codes);
$books = AudioBook::findBy('NoticeNr', $codes, true);
return array_values(array_map(array($this, 'AddFiles'), $books));
}
private function GetFiles(array $ids)
{
$ids = array_map('intval', $ids);
$uri = sprintf("%s%s",
Configuration::get('checkfile_url'),
http_build_query(array(
"client" => $this->client,
"login" => $this->login,
"book" => implode(',', $ids),
))
);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
$json = curl_exec($ch);
curl_close($ch);
return json_decode($json, true);
}
private function AddFiles(array $book)
{
$files = $this->GetFiles(array($book['code']));
if (is_array($files) && isset($files[$book['code']])) {
$book['files'] = $files[$book['code']];
} else {
$book['files'] = array();
}
return $book;
}
public function FindBook($code)
{
$this->CheckSession();
$code = intval($code);
$book = AudioBook::findBy('NoticeNr', $code, true);
return $this->AddFiles($book);
}
public function GetRandomBooks($number = 100) {
$sql = "SELECT TOP $number NoticeId
FROM Notices
WHERE
(
Notices.MediaType1Code='CDD' OR
Notices.MediaType1Code='CDA' OR
Notices.MediaType1Code='CDS'
)
AND Notices.Visible=1
AND Notices.[NoticeNr] NOT LIKE '%%~%%'
ORDER BY NEWID();";
$ids = Connection::execute($sql)->to_array();
$ids = array_map(function($a) { return $a['NoticeId']; }, $ids);
$books = AudioBook::findBy('NoticeId', $ids, true);
return array_values(array_map(array($this, 'AddFiles'), $books));
}
public function Search($query, $start, $limit)
{
$query = array(
'queryText' => $query,
'queryType' => is_numeric($query) && strlen($query) <= 5 ? 'code' : 'text',
'count' => $limit,
'page' => max(intval($start) - 1, 0),
);
$data = $this->NewSearch(json_encode($query));
// remove fields that are not used in "old" search
unset($data['count']);
unset($data['facets']);
return $data;
}
public function NewSearch($values)
{
$this->CheckSession();
$queryArray = json_decode($values, true);
if(! is_array($queryArray)) {
throw new WebException("CallArg", "Argument must be valid JSON.", -42);
}
// The iOS and Android applications still uses 'category' instead of 'genre'
if(isset($queryArray['category']) && is_array($queryArray['category'])) {
$queryArray['genre'] = $queryArray['category'];
unset($queryArray['category']);
}
$bs = new BookSearch();
if (isset($queryArray['queryType'])) {
$bs->addSortField('author', SolrQuery::ORDER_ASC);
$bs->addSortField('title', SolrQuery::ORDER_ASC);
$bs->addSortField('producerCode');
$bs->addSortField('mediaType', SolrQuery::ORDER_ASC);
} else {
$bs->addSortField('availabilityDate');
$bs->addSortField('author', SolrQuery::ORDER_ASC);
$bs->addSortField('title', SolrQuery::ORDER_ASC);
}
if (isset($queryArray['queryText']) && strlen($queryArray['queryText']) > 0) {
$type = isset($queryArray['queryType']) ? $queryArray['queryType'] : null;
if($this->client != 'website' && in_array($type, array('title', 'author', 'reader'))) {
// we don't want an exact search on mobile apps
$type = $type.'_fr';
}
$bs->addQuery($queryArray['queryText'], $type);
}
if(isset($queryArray['genre']) && is_array($queryArray['genre'])) {
$selectedGenres = array_filter($queryArray['genre'], function ($c) {
return $c != '0';
});
if (count($selectedGenres) > 0) {
$selectedGenres = array_map(function ($c) {
return 'genreCode:'.SolrUtils::escapeQueryChars($c);
}, $selectedGenres);
$bs->addQuery('('.implode(' OR ', $selectedGenres).')', null, false);
}
}
if(isset($queryArray['jeunesse']) && $queryArray['jeunesse']['filtrer'] === 'filtrer') {
$bs->addQuery(1, 'jeunesse');
}
// The following query filter is used by the mobile applications
if(isset($queryArray['producer']) && strlen($queryArray['producer']) > 0) {
$bs->addQuery($queryArray['producer'], 'producerCode');
}
$count = isset($queryArray['count']) ? (int) $queryArray['count'] : Configuration::get('solr.result_count');
$start = isset($queryArray['page']) ? $queryArray['page'] * $count : 0;
try {
$results = $bs->getResults($start, $count);
} catch(SolrClientException $e) {
throw new WebException ("SolrError", $e->getMessage(), -700);
}
$data = array(
'count' => $results['response']['numFound'],
'facets' => $results['facet_counts']['facet_fields'],
);
foreach ($results['response']['docs'] as $doc) {
$data[] = $this->AddFiles((array) $doc);
}
return $data;
}
public function ListOfReaders()
{
return AudioBook::listOfReaders();
}
public function ListOfGenres()
{
return AudioBook::ListOfGenres();
}
public function ListOfCategories()
{
// this method exists for compatibility purpose with the Android and iOS applications
return $this->ListOfGenres();
}
public function ListOfTypes()
{
return array_filter(AudioBook::listOfTypes(), function ($t) {
return strlen($t) > 0;
});
}
public function InReadingBooks()
{
return AudioBook::inReading();
}
public function LastBooksByType($type, $itemsByGroup)
{
$this->CheckSession();
$s = new BookSearch();
if($type == 'Jeunesse') {
$s->addQuery(1, 'jeunesse');
} else {
$s->addQuery($type, 'genre');
}
$s->addSortField('availabilityDate');
try {
$results = $s->getResults(0, $itemsByGroup);
} catch(SolrClientException $e) {
throw new WebException ("SolrError", $e->getMessage(), -710);
}
$ids = array_map(function($r) { return $r['id']; }, $results['response']['docs']);
$books = AudioBook::findBy('NoticeID', $ids, true);
$books = array_map(array($this, 'AddFiles'), $books);
$data = array();
foreach($books as $b) {
$data[$b['type']][] = $b;
}
return $data;
}
}