change line endings

master
Gilles Crettenand 11 years ago
parent 265ed19543
commit c0159f4b79

8
.gitignore vendored

@ -1,4 +1,4 @@
.idea
logs/
*configuration.local.php
*~
.idea
logs/
*configuration.local.php
*~

@ -1,106 +1,106 @@
<?php
namespace BSR\Lib;
class Configuration {
private static $instance = null;
/**
* ! WARNING !
*
* Those are default values, if you need to change them for a particular host,
* please just create a file named 'configuration.local.php' in the same directory
* and redefine the values there !
*
* This file must contain an array named $configuration containing the keys you
* want to redefine. Then, those values will be used to replace those in the
* array defined just below.
*
* @var array configuration values
*/
private $values = array(
'db' => array(
'driver' => 'SQL Server Native Client 11.0',
'server' => 'BSR2012\SQLEXPRESS',
'port' => '1433',
'username' => 'alcoda',
'password' => 'alcodaonly',
'name' => 'NetBiblio3',
),
'solr' => array(
'server' => '192.168.1.250',
'port' => '8983',
'username' => '',
'password' => '',
'path' => 'solr/bsr1',
'result_count' => 10,
),
'log' => array(
'file' => 'C:\inetpub\wwwroot\WebService\logs\log.txt',
// The greater the verbosity, the more is displayed
// 0 : no log at all
// 1 : log function calls and errors
// 2 : log parameters and sent data
'verbosity' => 0,
),
'session' => array(
'save_path' => ''
),
'checkfile_url' => 'http://fichiers.bibliothequesonore.ch/checkfile.php?',
'netbiblio_worker_id' => 45,
'www_employee_id' => 45,
'www_library_id' => 2,
);
private $custom_config = 'configuration.local.php';
private function __construct() {
// by default, set the session save path to the default value;
$this->values['session']['save_path'] = session_save_path();
if(file_exists($this->custom_config)) {
require_once($this->custom_config);
if(! isset($configuration) || ! is_array($configuration)) {
throw new \RuntimeException("You custom configuration in '{$this->custom_config}' must be in a variable named '\$configuration' and be an array.");
}
$this->values = array_replace_recursive($this->values, $configuration);
}
}
private function dotNotationAccess($data, $key, $default=null)
{
$keys = explode('.', $key);
foreach ($keys as $k) {
if (!is_array($data)) {
throw new \Exception("Try to access non-array as array, key '$key''");
}
if (!isset($data[$k])) {
return $default;
}
$data = $data[$k];
}
return $data;
}
private function value($name, $default) {
return $this->dotNotationAccess($this->values, $name, $default);
}
/**
* @param $name
* @param mixed $default the default value for your configuration option
* @return mixed return the configuration value if the key is find, the default otherwise
*/
public static function get($name, $default = null) {
if(is_null(self::$instance)) {
self::$instance = new Configuration();
}
return self::$instance->value($name, $default);
}
}
<?php
namespace BSR\Lib;
class Configuration {
private static $instance = null;
/**
* ! WARNING !
*
* Those are default values, if you need to change them for a particular host,
* please just create a file named 'configuration.local.php' in the same directory
* and redefine the values there !
*
* This file must contain an array named $configuration containing the keys you
* want to redefine. Then, those values will be used to replace those in the
* array defined just below.
*
* @var array configuration values
*/
private $values = array(
'db' => array(
'driver' => 'SQL Server Native Client 11.0',
'server' => 'BSR2012\SQLEXPRESS',
'port' => '1433',
'username' => 'alcoda',
'password' => 'alcodaonly',
'name' => 'NetBiblio3',
),
'solr' => array(
'server' => '192.168.1.250',
'port' => '8983',
'username' => '',
'password' => '',
'path' => 'solr/bsr1',
'result_count' => 10,
),
'log' => array(
'file' => 'C:\inetpub\wwwroot\WebService\logs\log.txt',
// The greater the verbosity, the more is displayed
// 0 : no log at all
// 1 : log function calls and errors
// 2 : log parameters and sent data
'verbosity' => 0,
),
'session' => array(
'save_path' => ''
),
'checkfile_url' => 'http://fichiers.bibliothequesonore.ch/checkfile.php?',
'netbiblio_worker_id' => 45,
'www_employee_id' => 45,
'www_library_id' => 2,
);
private $custom_config = 'configuration.local.php';
private function __construct() {
// by default, set the session save path to the default value;
$this->values['session']['save_path'] = session_save_path();
if(file_exists($this->custom_config)) {
require_once($this->custom_config);
if(! isset($configuration) || ! is_array($configuration)) {
throw new \RuntimeException("You custom configuration in '{$this->custom_config}' must be in a variable named '\$configuration' and be an array.");
}
$this->values = array_replace_recursive($this->values, $configuration);
}
}
private function dotNotationAccess($data, $key, $default=null)
{
$keys = explode('.', $key);
foreach ($keys as $k) {
if (!is_array($data)) {
throw new \Exception("Try to access non-array as array, key '$key''");
}
if (!isset($data[$k])) {
return $default;
}
$data = $data[$k];
}
return $data;
}
private function value($name, $default) {
return $this->dotNotationAccess($this->values, $name, $default);
}
/**
* @param $name
* @param mixed $default the default value for your configuration option
* @return mixed return the configuration value if the key is find, the default otherwise
*/
public static function get($name, $default = null) {
if(is_null(self::$instance)) {
self::$instance = new Configuration();
}
return self::$instance->value($name, $default);
}
}

@ -1,9 +1,9 @@
<?php
namespace BSR\Lib\Exception;
class BookNotFoundException extends WebException {
public function __construct($code) {
parent::__construct('BookNotFound', "The book with code $code was not found", -404);
}
}
<?php
namespace BSR\Lib\Exception;
class BookNotFoundException extends WebException {
public function __construct($code) {
parent::__construct('BookNotFound', "The book with code $code was not found", -404);
}
}

@ -1,8 +1,8 @@
<?php
namespace BSR\Lib\Exception;
/**
* Exception raised when an invalid attribute name is accessed
*/
class InvalidAttributeException extends \Exception { }
<?php
namespace BSR\Lib\Exception;
/**
* Exception raised when an invalid attribute name is accessed
*/
class InvalidAttributeException extends \Exception { }

@ -1,19 +1,19 @@
<?php
namespace BSR\Lib\Exception;
class SqlException extends \Exception
{
private $query;
public function __construct($message = "Sql Error", $query = "")
{
$this->query = $query;
parent::__construct($message, 0);
}
public function getSqlError()
{
return $this->getMessage().' while executing: '.$this->query;
}
}
<?php
namespace BSR\Lib\Exception;
class SqlException extends \Exception
{
private $query;
public function __construct($message = "Sql Error", $query = "")
{
$this->query = $query;
parent::__construct($message, 0);
}
public function getSqlError()
{
return $this->getMessage().' while executing: '.$this->query;
}
}

@ -1,24 +1,24 @@
<?php
namespace BSR\Lib\Exception;
class WebException extends \Exception
{
private $excname;
/**
* @param string $name
* @param string $reason
* @param int $code
*/
function __construct($name, $reason, $code)
{
$this->excname = $name;
parent::__construct($reason, $code);
}
public function getName()
{
return $this->excname;
}
}
<?php
namespace BSR\Lib\Exception;
class WebException extends \Exception
{
private $excname;
/**
* @param string $name
* @param string $reason
* @param int $code
*/
function __construct($name, $reason, $code)
{
$this->excname = $name;
parent::__construct($reason, $code);
}
public function getName()
{
return $this->excname;
}
}

@ -1,89 +1,89 @@
<?php
namespace BSR\Lib\Search;
use BSR\Lib\Configuration;
use BSR\Lib\Exception\WebException;
mb_http_output('UTF-8');
class BookSearch
{
/** @var \SolrClient */
private $client;
/** @var \SolrQuery */
private $query;
private $queryParts = array();
public function __construct()
{
$options = array
(
'hostname' => Configuration::get('solr.server'),
'port' => Configuration::get('solr.port'),
'login' => Configuration::get('solr.username'),
'password' => Configuration::get('solr.password'),
'path' => Configuration::get('solr.path'),
);
$this->client = new \SolrClient($options);
$this->query = new \SolrQuery();
$this->query->setQuery('*:*');
$this->query->addField('*');
$this->query->addParam('q.op', 'AND');
}
public function addQuery($queryText, $queryField = null, $escape = true)
{
if($escape) {
$queryText = \SolrUtils::escapeQueryChars($queryText);
}
if (strlen($queryField) > 0) {
$queryText = "$queryField:\"$queryText\"";
}
$this->queryParts[] = $queryText;
}
public function addSortField($field, $order = \SolrQuery::ORDER_DESC)
{
$this->query->addSortField($field, $order);
}
/**
* @param int $start
* @param int $count
* @return array
* @throws WebException
*/
public function getResults($start = 0, $count = 15)
{
if (count($this->queryParts) == 0)
$query = '*:*';
else {
$query = implode(' AND ', $this->queryParts);
}
$this->query->setQuery($query);
$this->query->setStart($start);
$this->query->setRows($count);
try {
$results = $this->client->query($this->query)->getResponse();
} catch(\SolrClientException $e) {
throw new WebException ("SolrError", $e->getMessage(), -700);
}
$books = isset($results['response']['docs']) && $results['response']['docs'] ?
array_map(function($o) { return (array) $o; }, $results['response']['docs']) :
array();
return array(
'count' => $results['response']['numFound'],
'facets' => $results['facet_counts']['facet_fields'],
'books' => $books,
);
}
}
<?php
namespace BSR\Lib\Search;
use BSR\Lib\Configuration;
use BSR\Lib\Exception\WebException;
mb_http_output('UTF-8');
class BookSearch
{
/** @var \SolrClient */
private $client;
/** @var \SolrQuery */
private $query;
private $queryParts = array();
public function __construct()
{
$options = array
(
'hostname' => Configuration::get('solr.server'),
'port' => Configuration::get('solr.port'),
'login' => Configuration::get('solr.username'),
'password' => Configuration::get('solr.password'),
'path' => Configuration::get('solr.path'),
);
$this->client = new \SolrClient($options);
$this->query = new \SolrQuery();
$this->query->setQuery('*:*');
$this->query->addField('*');
$this->query->addParam('q.op', 'AND');
}
public function addQuery($queryText, $queryField = null, $escape = true)
{
if($escape) {
$queryText = \SolrUtils::escapeQueryChars($queryText);
}
if (strlen($queryField) > 0) {
$queryText = "$queryField:\"$queryText\"";
}
$this->queryParts[] = $queryText;
}
public function addSortField($field, $order = \SolrQuery::ORDER_DESC)
{
$this->query->addSortField($field, $order);
}
/**
* @param int $start
* @param int $count
* @return array
* @throws WebException
*/
public function getResults($start = 0, $count = 15)
{
if (count($this->queryParts) == 0)
$query = '*:*';
else {
$query = implode(' AND ', $this->queryParts);
}
$this->query->setQuery($query);
$this->query->setStart($start);
$this->query->setRows($count);
try {
$results = $this->client->query($this->query)->getResponse();
} catch(\SolrClientException $e) {
throw new WebException ("SolrError", $e->getMessage(), -700);
}
$books = isset($results['response']['docs']) && $results['response']['docs'] ?
array_map(function($o) { return (array) $o; }, $results['response']['docs']) :
array();
return array(
'count' => $results['response']['numFound'],
'facets' => $results['facet_counts']['facet_fields'],
'books' => $books,
);
}
}

@ -1,122 +1,122 @@
<?php
namespace BSR\Lib;
use BSR\Lib\Exception\WebException;
abstract class WebService
{
private $func = null;
private $status = 200;
private $log = '';
/**
* @param $message
* @param int $verbosity
* @param bool $withTime
*/
public function log($message, $verbosity = 1, $withTime = false) {
if(Configuration::get('log.verbosity') < $verbosity) {
return;
}
if($withTime) {
$message = date("d-m-Y h:m:s").' '.$message;
}
$this->log .= $message."\n";
}
public function Run()
{
$this->log("------------------");
$this->log("Start request", 1, true);
$data = array();
try {
$result = $this->Call();
$data["result"][$this->func] = $result;
} catch (WebException $e) {
$data["error"]["code"] = $e->getCode();
$data["error"]["name"] = $e->getName();
$data["error"]["reason"] = $e->getMessage();
$this->status = 400;
$this->log(sprintf("Error : [%s] %s", $e->getCode(), $e->getName()));
} catch (\Exception $e) {
$data["failure"]["message"] = $e->getMessage();
$this->status = 500;
$this->log(sprintf("Failure : %s", $e->getMessage()));
}
$this->Send($data);
$this->log("Request finished", 1, true);
$this->log("------------------\n\n");
if(Configuration::get('log.verbosity') > 0) {
file_put_contents(Configuration::get('log.file'), $this->log, FILE_APPEND | LOCK_EX);
}
}
private function Call()
{
ob_start();
session_save_path(Configuration::get('session.save_path'));
session_start();
$params = empty($_GET) ? $_POST : $_GET;
if (empty($params)) {
throw new WebException ("CallArgument", "arguments error", -1);
}
if (!array_key_exists("func", $params)) {
throw new WebException ("CallArgFunction", "no 'func' specified", -2);
}
$this->func = $params["func"];
unset($params['func']);
if (!is_callable(array($this, $this->func))) {
throw new WebException ("CallFunction", "'func' method not available", -3);
}
$rm = new \ReflectionMethod($this, $this->func);
$nbParams = count($params);
$nbArgsFix = $rm->getNumberOfRequiredParameters();
$nbArgs = $rm->getNumberOfParameters();
/* Check the number of arguments. */
if ($nbParams < $nbArgsFix) {
throw new WebException ("CallArgNumber", "you must provide at least " . $nbArgsFix . " arguments", 4);
}
if ($nbParams > $nbArgs) {
throw new WebException ("CallArgNumber", "you must provide at most " . $nbArgs . " arguments", 4);
}
$this->log("Calling '".$this->func."'");
$this->log("Params: ".print_r($params, true), 2);
return call_user_func_array(array($this, $this->func), $params);
}
private function Send(array $data)
{
static $status_messages = array(
200 => 'Ok',
400 => 'Bad request',
404 => 'Not Found',
403 => 'Not Authorized',
500 => 'Server Error',
);
header(sprintf('HTTP/1.0 %s %s', $this->status, $status_messages[$this->status]));
ob_clean();
flush();
$this->log("Data: ".print_r($data, true), 2);
echo json_encode($data);
}
}
<?php
namespace BSR\Lib;
use BSR\Lib\Exception\WebException;
abstract class WebService
{
private $func = null;
private $status = 200;
private $log = '';
/**
* @param $message
* @param int $verbosity
* @param bool $withTime
*/
public function log($message, $verbosity = 1, $withTime = false) {
if(Configuration::get('log.verbosity') < $verbosity) {
return;
}
if($withTime) {
$message = date("d-m-Y h:m:s").' '.$message;
}
$this->log .= $message."\n";
}
public function Run()
{
$this->log("------------------");
$this->log("Start request", 1, true);
$data = array();
try {
$result = $this->Call();
$data["result"][$this->func] = $result;
} catch (WebException $e) {
$data["error"]["code"] = $e->getCode();
$data["error"]["name"] = $e->getName();
$data["error"]["reason"] = $e->getMessage();
$this->status = 400;
$this->log(sprintf("Error : [%s] %s", $e->getCode(), $e->getName()));
} catch (\Exception $e) {
$data["failure"]["message"] = $e->getMessage();
$this->status = 500;
$this->log(sprintf("Failure : %s", $e->getMessage()));
}
$this->Send($data);
$this->log("Request finished", 1, true);
$this->log("------------------\n\n");
if(Configuration::get('log.verbosity') > 0) {
file_put_contents(Configuration::get('log.file'), $this->log, FILE_APPEND | LOCK_EX);
}
}
private function Call()
{
ob_start();
session_save_path(Configuration::get('session.save_path'));
session_start();
$params = empty($_GET) ? $_POST : $_GET;
if (empty($params)) {
throw new WebException ("CallArgument", "arguments error", -1);
}
if (!array_key_exists("func", $params)) {
throw new WebException ("CallArgFunction", "no 'func' specified", -2);
}
$this->func = $params["func"];
unset($params['func']);
if (!is_callable(array($this, $this->func))) {
throw new WebException ("CallFunction", "'func' method not available", -3);
}
$rm = new \ReflectionMethod($this, $this->func);
$nbParams = count($params);
$nbArgsFix = $rm->getNumberOfRequiredParameters();
$nbArgs = $rm->getNumberOfParameters();
/* Check the number of arguments. */
if ($nbParams < $nbArgsFix) {
throw new WebException ("CallArgNumber", "you must provide at least " . $nbArgsFix . " arguments", 4);
}
if ($nbParams > $nbArgs) {
throw new WebException ("CallArgNumber", "you must provide at most " . $nbArgs . " arguments", 4);
}
$this->log("Calling '".$this->func."'");
$this->log("Params: ".print_r($params, true), 2);
return call_user_func_array(array($this, $this->func), $params);
}
private function Send(array $data)
{
static $status_messages = array(
200 => 'Ok',
400 => 'Bad request',
404 => 'Not Found',
403 => 'Not Authorized',
500 => 'Server Error',
);
header(sprintf('HTTP/1.0 %s %s', $this->status, $status_messages[$this->status]));
ob_clean();
flush();
$this->log("Data: ".print_r($data, true), 2);
echo json_encode($data);
}
}

@ -1,251 +1,251 @@
<?php
namespace BSR\Lib\db;
/**
* 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 reader
* @property string sql_reader
* @property string cover
* @property string sql_cover
* @property string category
* @property string sql_category
* @property string availabilityDate
* @property string sql_availabilityDate
* @property string producerCode
* @property string sql_producerCode
* @property string producer
* @property string sql_producer
* @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 mediaType
* @property string sql_mediaType
*/
class AudioBook extends DbMapping
{
protected $attributeNames = 'id title author code summary editor media collection isbn reader cover category availabilityDate producerCode producer genre genreCode coverdisplay link linkTitle mediaType';
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;
}
// The following query should be maintained in sync with the one in the solr data source.
$sql = sprintf("SELECT DISTINCT
Notices.[NoticeID] AS id,
LTRIM(RTRIM(Notices.[Title])) AS title,
LTRIM(RTRIM(Notices.[Author])) AS author,
LTRIM(RTRIM(Notices.[NoticeNr])) AS code,
Fields.[520] AS summary,
REPLACE(Fields.[260b], ',', '') AS editor,
LEFT(SUBSTRING(Fields.[260c], PATINDEX('%%[0-9]%%', Fields.[260c]), 8000), PATINDEX('%%[^0-9]%%', SUBSTRING(Fields.[260c], PATINDEX('%%[0-9]%%', Fields.[260c]), 8000) + 'X')-1) AS year,
Fields.[300] AS media,
Fields.[490a] AS collection,
LTRIM(RTRIM(isbn.DisplayText)) AS isbn,
Fields.[901] AS reader,
Fields.[899a] AS cover,
'' AS category, -- supposed to come from tags 600, 610, 650, 651, 655, 690, 691, 695, 696 but always empty anyway
item1.AcquisitionDate AS availabilityDate,
LTRIM(RTRIM(ProducerCode.TextFre)) As producer,
LTRIM(RTRIM(ProducerCode.Code)) AS producerCode,
LTRIM(RTRIM(GenreCode.TextFre)) As genre,
LTRIM(RTRIM(GenreCode.Code)) AS genreCode,
CASE
WHEN Notices.coverdisplay = 2 THEN 'http://fichiers.bibliothequesonore.ch:8089/netbiblio/images/covers/Cover' + CAST(Notices.NoticeID AS VARCHAR) + '_Original.jpg'
ELSE 'http://ecx.images-amazon.com/images/I/' + Fields.[899a] + '._SL320_.jpg'
END AS cover,
Fields.[856u] AS link,
Fields.[856z] AS linkTitle,
LTRIM(RTRIM(Notices.[MediaType1Code])) AS mediaType
FROM Notices
INNER JOIN Codes As GenreCode ON Notices.MediaType2Code = GenreCode.Code AND GenreCode.Type = 2
INNER JOIN Codes AS ProducerCode ON Notices.userdefined3code = ProducerCode.Code AND ProducerCode.Type=6
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 LTRIM(RTRIM(CAST(AuthorityID AS varchar)))
ELSE LTRIM(RTRIM(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
OUTER APPLY (
SELECT TOP 1 *
FROM Items
WHERE Notices.NoticeID = NoticeId
) AS item1
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()) {
$books[$row['id']] = $raw ? $row : new AudioBook($row);
}
return $multiple ? $books : reset($books);
}
/**
* 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 type available in the database.
* @param boolean $withJeunesse add 'Jeunesse' to the list
* @return array
*/
public static function ListOfGenres($withJeunesse = false)
{
$sql = "SELECT DISTINCT
LTRIM(RTRIM(Codes.Code)) as code,
LTRIM(RTRIM(Codes.TextFre)) AS text
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)->to_array();
if($withJeunesse) {
array_unshift($results, array('code' => 'J', 'text' => '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);
}
<?php
namespace BSR\Lib\db;
/**
* 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 reader
* @property string sql_reader
* @property string cover
* @property string sql_cover
* @property string category
* @property string sql_category
* @property string availabilityDate
* @property string sql_availabilityDate
* @property string producerCode
* @property string sql_producerCode
* @property string producer
* @property string sql_producer
* @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 mediaType
* @property string sql_mediaType
*/
class AudioBook extends DbMapping
{
protected $attributeNames = 'id title author code summary editor media collection isbn reader cover category availabilityDate producerCode producer genre genreCode coverdisplay link linkTitle mediaType';
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;
}
// The following query should be maintained in sync with the one in the solr data source.
$sql = sprintf("SELECT DISTINCT
Notices.[NoticeID] AS id,
LTRIM(RTRIM(Notices.[Title])) AS title,
LTRIM(RTRIM(Notices.[Author])) AS author,
LTRIM(RTRIM(Notices.[NoticeNr])) AS code,
Fields.[520] AS summary,
REPLACE(Fields.[260b], ',', '') AS editor,
LEFT(SUBSTRING(Fields.[260c], PATINDEX('%%[0-9]%%', Fields.[260c]), 8000), PATINDEX('%%[^0-9]%%', SUBSTRING(Fields.[260c], PATINDEX('%%[0-9]%%', Fields.[260c]), 8000) + 'X')-1) AS year,
Fields.[300] AS media,
Fields.[490a] AS collection,
LTRIM(RTRIM(isbn.DisplayText)) AS isbn,
Fields.[901] AS reader,
Fields.[899a] AS cover,
'' AS category, -- supposed to come from tags 600, 610, 650, 651, 655, 690, 691, 695, 696 but always empty anyway
item1.AcquisitionDate AS availabilityDate,
LTRIM(RTRIM(ProducerCode.TextFre)) As producer,
LTRIM(RTRIM(ProducerCode.Code)) AS producerCode,
LTRIM(RTRIM(GenreCode.TextFre)) As genre,
LTRIM(RTRIM(GenreCode.Code)) AS genreCode,
CASE
WHEN Notices.coverdisplay = 2 THEN 'http://fichiers.bibliothequesonore.ch:8089/netbiblio/images/covers/Cover' + CAST(Notices.NoticeID AS VARCHAR) + '_Original.jpg'
ELSE 'http://ecx.images-amazon.com/images/I/' + Fields.[899a] + '._SL320_.jpg'
END AS cover,
Fields.[856u] AS link,
Fields.[856z] AS linkTitle,
LTRIM(RTRIM(Notices.[MediaType1Code])) AS mediaType
FROM Notices
INNER JOIN Codes As GenreCode ON Notices.MediaType2Code = GenreCode.Code AND GenreCode.Type = 2
INNER JOIN Codes AS ProducerCode ON Notices.userdefined3code = ProducerCode.Code AND ProducerCode.Type=6
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 LTRIM(RTRIM(CAST(AuthorityID AS varchar)))
ELSE LTRIM(RTRIM(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
OUTER APPLY (
SELECT TOP 1 *
FROM Items
WHERE Notices.NoticeID = NoticeId
) AS item1
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()) {
$books[$row['id']] = $raw ? $row : new AudioBook($row);
}
return $multiple ? $books : reset($books);
}
/**
* 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 type available in the database.
* @param boolean $withJeunesse add 'Jeunesse' to the list
* @return array
*/
public static function ListOfGenres($withJeunesse = false)
{
$sql = "SELECT DISTINCT
LTRIM(RTRIM(Codes.Code)) as code,
LTRIM(RTRIM(Codes.TextFre)) AS text
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)->to_array();
if($withJeunesse) {
array_unshift($results, array('code' => 'J', 'text' => '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);
}
}

@ -1,187 +1,187 @@
<?php
namespace BSR\Lib\db;
use BSR\Lib\Configuration;
use BSR\Lib\Exception\SqlException;
class Connection
{
// Internal variable to hold the connection
private static $db;
final private function __construct() {}
/**
* @param $query
* @param bool $throw_error
* @return OdbcResultSet|resource|string
* @throws SqlException
*/
public static function execute($query, $throw_error = false)
{
$result = odbc_exec(self::get(), utf8_decode($query));
$result = new OdbcResultSet($result);
if ($result->is_error()) {
if($throw_error) {
throw new SqlException($result->get_error(), $query);
}
return $result->get_error();
}
return $result;
}
public static function get()
{
if (is_null(self::$db)) {
$dsn = sprintf(
"Driver={%s};Server=%s,%s;Database=%s;",
Configuration::get('db.driver'),
Configuration::get('db.server'),
Configuration::get('db.port'),
Configuration::get('db.name')
);
self::$db = odbc_pconnect($dsn, Configuration::get('db.username'), Configuration::get('db.password'));
if (self::$db === false) {
throw new SqlException("Unable to connect to the server.");
}
}
// Return the connection
return self::$db;
}
final private function __clone() {}
}
class OdbcResultSet implements \Iterator, \ArrayAccess
{
public $length;
private $results;
private $error;
private $num_fields;
private $cursor_index;
public function __construct($odbc_result)
{
if ($odbc_result === false) {
$this->error = odbc_errormsg(Connection::get());
} else {
try {
$this->results = array();
$this->num_fields = odbc_num_fields($odbc_result);
if ($this->num_fields > 0) {
while ($row = odbc_fetch_row($odbc_result)) {
$data = array();
for ($i = 1; $i <= $this->num_fields; ++$i) {
$data[odbc_field_name($odbc_result, $i)] = utf8_encode(odbc_result($odbc_result, $i));
}
$this->results[] = $data;
}
};
} catch (\Exception $e) {
print($e->getMessage());
}
$this->cursor_index = 0;
$this->length = count($this->results);
odbc_free_result($odbc_result);
}
}
public function is_error()
{
return ($this->error ? true : false);
}
public function get_error()
{
return $this->error;
}
public function get_row()
{
return $this->current();
}
public function to_array()
{
return $this->results;
}
// ArrayAccess
/**
* @param int $offset
* @return bool
*/
public function offsetExists($offset)
{
return !$this->error && $this->cursor_index < $this->length && $this->cursor_index >= 0;
}
/**
* @param int $offset
* @return bool|array
*/
public function offsetGet($offset)
{
return $this->offsetExists($offset) ? $this->results[$offset] : false;
}
public function offsetSet($offset, $value)
{
if($this->offsetExists($offset)) {
$this->results[$offset] = $value;
}
}
public function offsetUnset($offset)
{
throw new \RuntimeException("This makes no sense at all.");
}
// Iterator
/**
* @return bool|array
*/
public function current()
{
return $this->offsetGet($this->cursor_index);
}
/**
* @return int
*/
public function key()
{
return $this->cursor_index;
}
/**
* @return array|bool
*/
public function next()
{
$current = $this->current();
++$this->cursor_index;
return $current;
}
public function rewind()
{
$this->cursor_index = 0;
}
/**
* @return bool
*/
public function valid()
{
return $this->offsetExists($this->cursor_index);
}
<?php
namespace BSR\Lib\db;
use BSR\Lib\Configuration;
use BSR\Lib\Exception\SqlException;
class Connection
{
// Internal variable to hold the connection
private static $db;
final private function __construct() {}
/**
* @param $query
* @param bool $throw_error
* @return OdbcResultSet|resource|string
* @throws SqlException
*/
public static function execute($query, $throw_error = false)
{
$result = odbc_exec(self::get(), utf8_decode($query));
$result = new OdbcResultSet($result);
if ($result->is_error()) {
if($throw_error) {
throw new SqlException($result->get_error(), $query);
}
return $result->get_error();
}
return $result;
}
public static function get()
{
if (is_null(self::$db)) {
$dsn = sprintf(
"Driver={%s};Server=%s,%s;Database=%s;",
Configuration::get('db.driver'),
Configuration::get('db.server'),
Configuration::get('db.port'),
Configuration::get('db.name')
);
self::$db = odbc_pconnect($dsn, Configuration::get('db.username'), Configuration::get('db.password'));
if (self::$db === false) {
throw new SqlException("Unable to connect to the server.");
}
}
// Return the connection
return self::$db;
}
final private function __clone() {}
}
class OdbcResultSet implements \Iterator, \ArrayAccess
{
public $length;
private $results;
private $error;
private $num_fields;
private $cursor_index;
public function __construct($odbc_result)
{
if ($odbc_result === false) {
$this->error = odbc_errormsg(Connection::get());
} else {
try {
$this->results = array();
$this->num_fields = odbc_num_fields($odbc_result);
if ($this->num_fields > 0) {
while ($row = odbc_fetch_row($odbc_result)) {
$data = array();
for ($i = 1; $i <= $this->num_fields; ++$i) {
$data[odbc_field_name($odbc_result, $i)] = utf8_encode(odbc_result($odbc_result, $i));
}
$this->results[] = $data;
}
};
} catch (\Exception $e) {
print($e->getMessage());
}
$this->cursor_index = 0;
$this->length = count($this->results);
odbc_free_result($odbc_result);
}
}
public function is_error()
{
return ($this->error ? true : false);
}
public function get_error()
{
return $this->error;
}
public function get_row()
{
return $this->current();
}
public function to_array()
{
return $this->results;
}
// ArrayAccess
/**
* @param int $offset
* @return bool
*/
public function offsetExists($offset)
{
return !$this->error && $this->cursor_index < $this->length && $this->cursor_index >= 0;
}
/**
* @param int $offset
* @return bool|array
*/
public function offsetGet($offset)
{
return $this->offsetExists($offset) ? $this->results[$offset] : false;
}
public function offsetSet($offset, $value)
{
if($this->offsetExists($offset)) {
$this->results[$offset] = $value;
}
}
public function offsetUnset($offset)
{
throw new \RuntimeException("This makes no sense at all.");
}
// Iterator
/**
* @return bool|array
*/
public function current()
{
return $this->offsetGet($this->cursor_index);
}
/**
* @return int
*/
public function key()
{
return $this->cursor_index;
}
/**
* @return array|bool
*/
public function next()
{
$current = $this->current();
++$this->cursor_index;
return $current;
}
public function rewind()
{
$this->cursor_index = 0;
}
/**
* @return bool
*/
public function valid()
{
return $this->offsetExists($this->cursor_index);
}
}

@ -1,126 +1,126 @@
<?php
namespace BSR\Lib\db;
use BSR\Lib\Exception\InvalidAttributeException;
/**
* Base class for mapping objects. inherit you database filled objects from here.
*
* @property int $id
*/
abstract class DbMapping
{
protected $attributes;
protected $attributeNames = '';
protected $privateAttributeNames = '';
/**
* @param array $attributes
*/
public function __construct(array $attributes)
{
$this->setAttributes($attributes);
}
/**
* Define a bunch of attribute given by an associative array
* @param array $attributes
*/
public function setAttributes(array $attributes)
{
$this->assertAttributes($attributes);
foreach ($attributes as $key => $value) {
$this->__set($key, $value);
}
}
/**
* Ensure that all keys from attributes are authorized
* @param array $attributes
*/
private function assertAttributes(array $attributes)
{
foreach ($attributes as $key => $value) {
$this->assertAttribute($key);
}
}
/**
* Ensure that name attribute is authorized
* If public_only is false, check agains PRIVATE_ATTRIBUTES_NAME too.
* Those one cannot be accessed via setAttributes and other batch methods.
* @param string $name
* @param bool $public_only
* @throws InvalidAttributeException if the attribute is not a valid one
*/
private function assertAttribute($name, $public_only = TRUE)
{
if (strpos($this->attributeNames, $name) === false && ($public_only || strpos($this->privateAttributeNames, $name) === false)) {
throw(new InvalidAttributeException("The attribute $name is invalid"));
}
}
/**
* Get a user attribute or the linked whishes
* @param string $name
* @return mixed
*/
public function __get($name)
{
$sql_safe = FALSE;
if (strpos($name, 'sql_') === 0) {
$name = substr($name, 4);
$sql_safe = TRUE;
}
$this->assertAttribute($name, false);
if (isset($this->attributes[$name])) {
$value = $this->attributes[$name];
if ($sql_safe) {
$value = str_replace("'", "''", $value);
}
return $value;
} else {
return NULL;
}
}
public function to_array() {
return $this->attributes;
}
/**
* Set a user attribute
* @param string $name
* @param mixed $value
*/
public function __set($name, $value)
{
$this->assertAttribute($name, false);
$this->attributes[$name] = $value;
}
/**
* Function to retrieve data from an id.
* @param int $id
* @return DbMapping
*/
public static function find($id) {
throw new \RuntimeException("This method must be implemented in child classes.");
}
/**
* Return all the public attributes in an array;
*/
public function toArray()
{
$result = array();
foreach ($this->attributes as $name => $value) {
if (strpos($this->attributeNames, $name) !== false) {
$result[$name] = $value;
}
}
return $result;
}
}
<?php
namespace BSR\Lib\db;
use BSR\Lib\Exception\InvalidAttributeException;
/**
* Base class for mapping objects. inherit you database filled objects from here.
*
* @property int $id
*/
abstract class DbMapping
{
protected $attributes;
protected $attributeNames = '';
protected $privateAttributeNames = '';
/**
* @param array $attributes
*/
public function __construct(array $attributes)
{
$this->setAttributes($attributes);
}
/**
* Define a bunch of attribute given by an associative array
* @param array $attributes
*/
public function setAttributes(array $attributes)
{
$this->assertAttributes($attributes);
foreach ($attributes as $key => $value) {
$this->__set($key, $value);
}
}
/**
* Ensure that all keys from attributes are authorized
* @param array $attributes
*/
private function assertAttributes(array $attributes)
{
foreach ($attributes as $key => $value) {
$this->assertAttribute($key);
}
}
/**
* Ensure that name attribute is authorized
* If public_only is false, check agains PRIVATE_ATTRIBUTES_NAME too.
* Those one cannot be accessed via setAttributes and other batch methods.
* @param string $name
* @param bool $public_only
* @throws InvalidAttributeException if the attribute is not a valid one
*/
private function assertAttribute($name, $public_only = TRUE)
{
if (strpos($this->attributeNames, $name) === false && ($public_only || strpos($this->privateAttributeNames, $name) === false)) {
throw(new InvalidAttributeException("The attribute $name is invalid"));
}
}
/**
* Get a user attribute or the linked whishes
* @param string $name
* @return mixed
*/
public function __get($name)
{
$sql_safe = FALSE;
if (strpos($name, 'sql_') === 0) {
$name = substr($name, 4);
$sql_safe = TRUE;
}
$this->assertAttribute($name, false);
if (isset($this->attributes[$name])) {
$value = $this->attributes[$name];
if ($sql_safe) {
$value = str_replace("'", "''", $value);
}
return $value;
} else {
return NULL;
}
}
public function to_array() {
return $this->attributes;
}
/**
* Set a user attribute
* @param string $name
* @param mixed $value
*/
public function __set($name, $value)
{
$this->assertAttribute($name, false);
$this->attributes[$name] = $value;
}
/**
* Function to retrieve data from an id.
* @param int $id
* @return DbMapping
*/
public static function find($id) {
throw new \RuntimeException("This method must be implemented in child classes.");
}
/**
* Return all the public attributes in an array;
*/
public function toArray()
{
$result = array();
foreach ($this->attributes as $name => $value) {
if (strpos($this->attributeNames, $name) !== false) {
$result[$name] = $value;
}
}
return $result;
}
}

@ -1,209 +1,209 @@
<?php
namespace BSR\Lib\db;
use BSR\Lib\Configuration;
/**
* 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
{
public static $tableName = 'Useraccounts';
public static $idColumn = 'UseraccountID';
protected static $addressTableName = 'Addresses';
protected static $addressIdColumn = 'AddressID';
protected static $wishTableName = 'Wishes';
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,
[%s] AS id,
REPLACE(UseraccountNr, ' ', '') AS login
FROM [%s] AS u
LEFT JOIN [%s] AS a ON a.[%s] = u.[ActualAddressID]
WHERE REPLACE(UseraccountNr, ' ', '') = '%s' AND disabled = 1 %s;",
self::$idColumn, self::$tableName, self::$addressTableName, self::$addressIdColumn, $login, $cond);
$results = Connection::execute($sql, $raiseError);
return $results->current() !== false ? new User($results->current()) : null;
}
private function _getCirculations($table, $sort = "ItemNr ASC") {
$sql = sprintf("SELECT
NoticeID,
CheckOutDate,
ItemNr
FROM %s AS c
INNER JOIN Items AS i ON i.ItemId = c.ItemId
WHERE
c.UseraccountId = %s
ORDER BY %s", $table, $this->id, $sort);
$result = Connection::execute($sql);
$circulations = $result->to_array();
$books = array_map(function($c) { return $c['NoticeID']; }, $circulations);
$books = AudioBook::findBy('NoticeID', $books, true);
foreach($circulations as $c) {
$books[$c['NoticeID']]['date'] = $c['CheckOutDate'];
$books[$c['NoticeID']]['itemNr'] = $c['ItemNr'];
}
return $books;
}
public function getCirculations()
{
return $this->_getCirculations('Circulations');
}
public function getOldCirculations()
{
return $this->_getCirculations('OldCirculations', 'CheckOutDate DESC');
}
/**
* 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 %s
(WishID, NoticeID, %s, CreationDate, EmployeeID, BranchOfficeID, Remark, ModificationDate)
SELECT %s , NoticeID, %s, GETDATE() , %s , %s , '' , GETDATE()
FROM Notices
WHERE LTRIM(RTRIM(NoticeNr)) = '%s';",
User::$wishTableName, User::$idColumn, $row['WishID'], $this->id, $employee_id, $library_id, $noticeNr);
Connection::execute($sql);
return true;
}
/**
* 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 int $limit
* @return AudioBook[]
*/
public function getWishes($limit = 50)
{
$sql = sprintf("SELECT TOP $limit
NoticeID
FROM %s
WHERE %s = %s
ORDER BY CreationDate DESC"
,User::$wishTableName, User::$idColumn, $this->id);
$result = Connection::execute($sql);
$ids = array_map(function($r) { return $r['NoticeID']; }, $result->to_array());
return AudioBook::findBy('NoticeID', $ids, true);
}
/**
* Remove a book from the wish list
* @param string $noticeNr
*/
public function deleteWish($noticeNr)
{
$sql = sprintf("DELETE w
FROM %s AS w
INNER JOIN Notices AS n ON n.NoticeID = w.NoticeID
WHERE
LTRIM(RTRIM(n.NoticeNr)) = '%s'
AND %s = %s;", User::$wishTableName, $noticeNr, User::$idColumn, $this->id);
Connection::execute($sql, true);
}
<?php
namespace BSR\Lib\db;
use BSR\Lib\Configuration;
/**
* 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
{
public static $tableName = 'Useraccounts';
public static $idColumn = 'UseraccountID';
protected static $addressTableName = 'Addresses';
protected static $addressIdColumn = 'AddressID';
protected static $wishTableName = 'Wishes';
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,
[%s] AS id,
REPLACE(UseraccountNr, ' ', '') AS login
FROM [%s] AS u
LEFT JOIN [%s] AS a ON a.[%s] = u.[ActualAddressID]
WHERE REPLACE(UseraccountNr, ' ', '') = '%s' AND disabled = 1 %s;",
self::$idColumn, self::$tableName, self::$addressTableName, self::$addressIdColumn, $login, $cond);
$results = Connection::execute($sql, $raiseError);
return $results->current() !== false ? new User($results->current()) : null;
}
private function _getCirculations($table, $sort = "ItemNr ASC") {
$sql = sprintf("SELECT
NoticeID,
CheckOutDate,
ItemNr
FROM %s AS c
INNER JOIN Items AS i ON i.ItemId = c.ItemId
WHERE
c.UseraccountId = %s
ORDER BY %s", $table, $this->id, $sort);
$result = Connection::execute($sql);
$circulations = $result->to_array();
$books = array_map(function($c) { return $c['NoticeID']; }, $circulations);
$books = AudioBook::findBy('NoticeID', $books, true);
foreach($circulations as $c) {
$books[$c['NoticeID']]['date'] = $c['CheckOutDate'];
$books[$c['NoticeID']]['itemNr'] = $c['ItemNr'];
}
return $books;
}
public function getCirculations()
{
return $this->_getCirculations('Circulations');
}
public function getOldCirculations()
{
return $this->_getCirculations('OldCirculations', 'CheckOutDate DESC');
}
/**
* 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 %s
(WishID, NoticeID, %s, CreationDate, EmployeeID, BranchOfficeID, Remark, ModificationDate)
SELECT %s , NoticeID, %s, GETDATE() , %s , %s , '' , GETDATE()
FROM Notices
WHERE LTRIM(RTRIM(NoticeNr)) = '%s';",
User::$wishTableName, User::$idColumn, $row['WishID'], $this->id, $employee_id, $library_id, $noticeNr);
Connection::execute($sql);
return true;
}
/**
* 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 int $limit
* @return AudioBook[]
*/
public function getWishes($limit = 50)
{
$sql = sprintf("SELECT TOP $limit
NoticeID
FROM %s
WHERE %s = %s
ORDER BY CreationDate DESC"
,User::$wishTableName, User::$idColumn, $this->id);
$result = Connection::execute($sql);
$ids = array_map(function($r) { return $r['NoticeID']; }, $result->to_array());
return AudioBook::findBy('NoticeID', $ids, true);
}
/**
* Remove a book from the wish list
* @param string $noticeNr
*/
public function deleteWish($noticeNr)
{
$sql = sprintf("DELETE w
FROM %s AS w
INNER JOIN Notices AS n ON n.NoticeID = w.NoticeID
WHERE
LTRIM(RTRIM(n.NoticeNr)) = '%s'
AND %s = %s;", User::$wishTableName, $noticeNr, User::$idColumn, $this->id);
Connection::execute($sql, true);
}
}

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
# README #
This repository contains the code for the WebService used internally at the [BSR](http://bibliothequesonore.ch/) by the Drupal website and both the iOS and Android applications.
# README #
This repository contains the code for the WebService used internally at the [BSR](http://bibliothequesonore.ch/) by the Drupal website and both the iOS and Android applications.
For more information, please consult the internal documentation : http://192.168.1.250/dokuwiki/doku.php?id=webservice

@ -1,20 +1,20 @@
<?php
namespace BSR;
ini_set('display_errors', 'On');
// register an autoloader to automatically load classes
// the namespace for the class must begin with BSR and
// otherwise respect the PSR-4 standard
spl_autoload_register(function ($class) {
$class = substr($class, strlen('BSR'));
$path = sprintf('%s/%s.php', __DIR__, str_replace('\\', '/', $class));
if (file_exists($path)) {
require $path;
}
});
$web = new NetBiblio();
$web->Run();
<?php
namespace BSR;
ini_set('display_errors', 'On');
// register an autoloader to automatically load classes
// the namespace for the class must begin with BSR and
// otherwise respect the PSR-4 standard
spl_autoload_register(function ($class) {
$class = substr($class, strlen('BSR'));
$path = sprintf('%s/%s.php', __DIR__, str_replace('\\', '/', $class));
if (file_exists($path)) {
require $path;
}
});
$web = new NetBiblio();
$web->Run();

@ -1,4 +1,4 @@
<?php
// this file is here for compatibility purpose, do not delete
<?php
// this file is here for compatibility purpose, do not delete
require_once('index.php');
Loading…
Cancel
Save