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.

331 lines
12 KiB
PHP

<?php
namespace BSR\Lib\db;
use BSR\Lib\Configuration;
use BSR\Lib\Search\BookSearch;
use BSR\Lib\Logger;
/**
* User is mapped on the UserAccounts table. Contains user information : id, login, firstName, lastName, displayName.
*
* @property int id
* @property string $login
* @property string $sql_login
* @property string $password
* @property string $sql_password
* @property string $privatePhone
* @property string $sql_privatePhone
* @property string $officePhone
* @property string $sql_officePhone
* @property string $mobilePhone
* @property string $sql_mobilePhone
* @property string $addressId
* @property string $sql_addressId
* @property string $displayName
* @property string $sql_displayName
* @property string $firstName
* @property string $sql_firstName
* @property string $lastName
* @property string $sql_lastName
* @property string $mail
* @property string $sql_mail
*/
class User extends DbMapping
{
protected $attributeNames = 'id login firstName lastName displayName freeOne mail addressId mobilePhone officePhone privatePhone';
protected $privateAttributeNames = 'password';
/**
* @param string $login Login for the user
* @param string $password Password for the user
* @return User|null User object if we were able to authenticate
*/
public static function authenticate($login, $password)
{
$password = str_replace("'", "''", $password);
return User::find($login, " UPPER(password) = UPPER('$password') ", false);
}
/**
* Retrieve a user by its login. Do not represent a valid authentication.
*
* Cond has to be safe because no check are made inside.
*
* @param string $login login the login name
* @param string $cond a condition to restrict the choice, optional
* @param bool $raiseError
* @return User the User object or NULL if no user found.
*/
public static function find($login, $cond = '', $raiseError = true)
{
$login = str_replace("'", "''", $login);
if(strlen($cond) > 0) {
$cond = " AND $cond";
}
$sql = sprintf("SELECT TOP 1
[FirstName] AS firstName,
[LastName] AS lastName,
[DisplayName] AS displayName,
[UserDefined1] AS freeOne,
[ActualAddressID] AS addressId,
[Email] AS mail,
[TelephoneMobile] AS mobilePhone,
[TelephonePrivate] AS privatePhone,
[Telephone] AS officePhone,
[UserAccountID] AS id,
REPLACE(UserAccountNr, ' ', '') AS login
FROM [UserAccounts] AS u
LEFT JOIN [Addresses] AS a ON a.[AddressID] = u.[ActualAddressID]
WHERE LTRIM(RTRIM(UserAccountNr)) = '%s' AND disabled = 1 %s AND CategoryCode in ('A', 'M', 'G', 'D', 'I', 'EMP');",
$login, $cond);
$results = Connection::execute($sql, $raiseError);
return $results->current() !== false ? new User($results->current()) : null;
}
/**
* Circulations as needed for the BSR internal tools
*/
public function GetCirculations()
{
$sql = sprintf("SELECT
n.NoticeID,
ItemNr,
LTRIM(RTRIM(n.NoticeNr)) AS code,
LTRIM(RTRIM(n.Title)) AS Title,
LTRIM(RTRIM(n.Author)) AS author,
Fields.[300] AS media,
Fields.[901] AS readBy
FROM Circulations AS c
INNER JOIN Items AS i ON i.ItemId = c.ItemId
INNER JOIN Notices AS n ON n.NoticeID = i.NoticeID
LEFT OUTER JOIN (
SELECT *
FROM (
SELECT
NoticeID,
Tag AS Field,
NoticeFields.ContentShortPart AS Data
FROM NoticeFields
WHERE Tag IN ('901', '300')
) AS src
PIVOT (
MIN(Data)
FOR Field IN ([901], [300])
) AS pvt
) Fields ON n.NoticeID = Fields.NoticeID
WHERE
c.UserAccountID = %s
ORDER BY ItemNr ASC", $this->id);
$result = Connection::execute($sql);
return $result ? $result->to_array() : array();
}
public function GetOldLoansNrs()
{
$sql = sprintf("SELECT
n.NoticeNr
FROM OldCirculations AS c
INNER JOIN Items AS i ON i.ItemId = c.ItemId
INNER JOIN Notices AS n ON n.NoticeID = i.NoticeID
WHERE
c.UserAccountID = %s AND
n.MediaType1Code in ('CDD', 'CDA', 'DVD', 'CDS') AND n.deleted=1
ORDER BY ItemNr ASC", $this->id);
$result = Connection::execute($sql);
return $result ? $result->to_array() : array();
}
public function getLoansData($table, $sort = "acquisitiondate DESC")
{
$sql = sprintf("SELECT top 50
realn.NoticeId as NoticeID,
realn.NoticeNr,
CheckOutDate,
c.Remark,
ItemNr
FROM %s AS c
INNER JOIN Items AS i ON i.ItemId = c.ItemId
INNER JOIN Notices AS lentn ON lentn.NoticeID = i.NoticeID
INNER JOIN Notices AS realn ON REPLACE(ltrim(rtrim(lentn.noticenr)), 'V', '') = ltrim(rtrim(realn.noticenr))
WHERE
c.UserAccountID = %s
ORDER BY %s", $table, $this->id, $sort);
return Connection::execute($sql)->to_array();
}
private function _getLoans($table, $count, $sort)
{
$circulations = $this->getLoansData($table, $sort);
//Logger::log(print_r($circulations, true));
// getting the intval of the NoticeNr will remove any 'V' or 'T' and thus we will have no issues with
// the virtual books that are used for Downloads and so.
$codes = array_unique(array_map(function($c) {
return trim($c['NoticeNr']); }, $circulations));
if($count) {
return count($circulations);
}
$books = count($codes) > 0 ? BookSearch::GetBooks($codes) : array();
//Logger::log(print_r($books, true));
foreach($circulations as $c) {
$id = $c['NoticeID'];
if(isset($books[$id])) {
$books[$id]['checkoutDate'] = $c['CheckOutDate'];
$books[$id]['remark'] = $c['Remark'];
}
}
return $books;
}
/**
* Loans (Circulations) as needed on the website
* @param boolean $count return only the count
* @return array
*/
public function GetLoans($count = false)
{
return $this->_getLoans('Circulations', $count, "ItemNr ASC");
}
/**
* Old loans (OldCirculations) as needed on the website
* @param boolean $count return only the count
* @return array
*/
public function GetOldLoans($count = false)
{
return $this->_getLoans('OldCirculations', $count, 'CheckOutDate DESC');
}
/**
* Books eligible for feedback by the user. Lent or downloaded more than 2 weeks ago and less than 5 monthes.
* @return array
*/
public function GetBooksForFeedback()
{
$sql = sprintf("SELECT n.NoticeNr
FROM OldCirculations AS c
INNER JOIN Items AS i ON i.ItemId = c.ItemId
INNER JOIN Notices AS n ON n.NoticeID = i.NoticeID
WHERE
c.UserAccountID = %s
AND DATEDIFF(month, CheckOutDate, GETDATE()) < 5
", $this->id);
return Connection::execute($sql)->to_array(); }
/**
* Add a book to the wish list if it is not already inside.
* @param string $noticeNr
* @return bool
*/
public function addWish($noticeNr)
{
if ($this->hasWish($noticeNr)) {
return false;
}
$sql = "UPDATE Counters
SET WishID = WishID + 1
OUTPUT INSERTED.WishID;";
$result = Connection::execute($sql, true);
$row = $result->current();
$employee_id = Configuration::get('www_employee_id');
$library_id = Configuration::get('www_library_id');
$sql = sprintf("INSERT INTO Wishes
(WishID, NoticeID, UserAccountID, CreationDate, EmployeeID, BranchOfficeID, Remark, ModificationDate)
SELECT %s , NoticeID, %s, GETDATE() , %s , %s , '' , GETDATE()
FROM Notices
WHERE LTRIM(RTRIM(NoticeNr)) = '%s';",
$row['WishID'], $this->id, $employee_id, $library_id, $noticeNr);
$status = Connection::execute($sql);
return $status && ! $status->is_error() && $status->get_num_rows() > 0;
}
/**
* Return true if the book is in the wish list
* @param string $noticeNr
* @return bool
*/
private function hasWish($noticeNr)
{
$sql = sprintf("SELECT w.NoticeID
FROM Wishes AS w
INNER JOIN Notices AS n ON n.NoticeID = w.NoticeID
WHERE
LTRIM(RTRIM(n.NoticeNr)) = '%s'
AND w.UserAccountID = %s;", $noticeNr, $this->id);
$result = Connection::execute($sql);
return $result->current() !== false;
}
/**
* Wishes are all the books that this user want to read.
* @param boolean $count return only the count
* @param int $limit
* @return array
*/
public function getWishes($count = false, $limit = 200)
{
$sql = sprintf("SELECT TOP $limit
NoticeID, CreationDate
FROM Wishes
WHERE UserAccountID = %s
ORDER BY CreationDate DESC", $this->id);
$result = Connection::execute($sql);
$wishList = $result->to_array();
$ids = array_map(function($r) { return $r['NoticeID']; }, $wishList);
if($count) {
return count($ids);
}
$books = BookSearch::GetBooks($ids, 'id');
foreach($wishList as $w) {
$id = $w['NoticeID'];
if(isset($books[$id])) {
$books[$id]['creationDate'] = $w['CreationDate'];
}
}
$creationDates = array();
foreach ($books as $key => $book)
{
$creationDates[$key] = $book['creationDate'];
}
array_multisort($creationDates, SORT_DESC, $books);
return $books;
}
/**
* Remove a book from the wish list
* @param string $noticeNr
* @return boolean Was the deletion was successful or not ?
*/
public function deleteWish($noticeNr)
{
$sql = sprintf("DELETE w
FROM Wishes AS w
INNER JOIN Notices AS n ON n.NoticeID = w.NoticeID
WHERE
LTRIM(RTRIM(n.NoticeNr)) = '%s'
AND UserAccountID = %s;", $noticeNr, $this->id);
$status = Connection::execute($sql, true);
return $status && ! $status->is_error() && $status->get_num_rows() > 0;
}
}