From 4acc4b0b4dcbf18afe25328b6d149cba7ae52130 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Thu, 22 Feb 2024 11:04:15 -0800
Subject: [PATCH 1/8] Functions that allow multiple optional parameters now
take an off on off off off off off off off off on off on off off off off off
on off off off on on off off off off on off off off off off off off off off
off off off on off off on off off off on on off on on off off off on off off
on off off on off off on off on off off on off on off off off off on off off
off on off off on off off off off off off off off on off on off off on off
off off off off off off on off off off off on off on off on off on off on on
off on off off on on on off on on off on on on on off off off off on on off
off on off off off off off on off off on off off on on off off off off off on
off off off off on on off on off off on off off on off on off off off off off
off off off off off on on off on off off off array. The README.md now lists
the available options. The registration scripts have been updated to match.
---
README.md | 28 +++++++++++----
src/Libilsws.php | 74 +++++++++++++++++++++++-----------------
test/register_patron.php | 11 +++---
test/register_staff.php | 8 +++--
4 files changed, 76 insertions(+), 45 deletions(-)
diff --git a/README.md b/README.md
index 264ad95..5424312 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,8 @@ if presented with inappropriate inputs.
- authenticate_patron($token, $patron_id, $password)
- change_barcode($token, $patron_key, $patron_id)
- change_item_library($token, $item_key, $library)
-- change_patron_password($token, $json)
+- change_patron_password($token, $json, $options)
+ Options array may include: role, client_id
- delete_patron($token, $patron_key)
- describe_bib($token)
- describe_item($token)
@@ -68,12 +69,16 @@ or evaluating data from the Symphony system.
- get_patron_checkouts($token, $patron_key, $include_fields)
- get_patron_indexes($token)
- prepare_search($terms)
-- register_patron($patron, $token, $addr_num, $role, $client_id, $template, $subject)
-- reset_patron_password($token, $patron_id, $url, $email, $role, $client_id)
+- register_patron($patron, $token, $addr_num, $options)
+ Options array may include: role, client_id, template, subject
+- reset_patron_password($token, $patron_id, $url, $email)
+ Optional: email
- search_authenticate($token, $index, $search, $password)
- search_bib($token, $index, $value, $params)
+ Params array may include: q, ct, rw, j, includeFields
- update_patron($patron, $token, $patron_key, $addr_num)
- update_patron_activeid($token, $patron_key, $patron_id, $option)
+ Option may be: a, i, d
- update_phone_list($phone_list, $token, $patron_key)
## Date and Telephone Number Formats
@@ -134,7 +139,12 @@ $response = $ilsws->get_patron_attributes($token, $patron_key);
```
/**
* The order of the fields doesn't matter. Not all of these are actually required.
- * See the YAML configuration file to determine which fields are required.
+ * See the YAML configuration file to determine which fields are required. If an
+ * email template name is included in the options array, an email will be sent to the
+ * patron. Actual template files must include a language extension (for example .en for
+ * English. The system will look for template that matches the patrons language
+ * preference. If one is found, it will use that, otherwise it will attempt to
+ * find and use an English template.
*/
$patron = [
'birthDate' => '1962-03-07',
@@ -165,10 +175,14 @@ $patron = [
];
$addr_num = 1;
-$role = 'STAFF';
-$client_id = 'StaffClient';
-$response = $ilsws->register_patron($patron, $token, $addr_num, $role, $client_id, $template);
+$options = [];
+$options['role'] = 'STAFF';
+$options['client_id'] = 'StaffClient';
+$options['template'] = 'template.html.twig';
+$options['subject'] = 'Welcome to the library!';
+
+$response = $ilsws->register_patron($patron, $token, $addr_num, $options);
```
### Update Patron Record
diff --git a/src/Libilsws.php b/src/Libilsws.php
index 68f6c92..ad47771 100644
--- a/src/Libilsws.php
+++ b/src/Libilsws.php
@@ -196,7 +196,6 @@ public function connect ()
} catch (APIException $e) {
echo $e->errorMessage($this->error, $this->code), "\n";
- exit(1);
}
return $token;
@@ -283,7 +282,6 @@ public function send_get ($url = null, $token = null, $params = null)
} catch (APIException $e) {
echo $e->errorMessage($this->error, $this->code), "\n";
- exit(1);
}
return json_decode($json, true);
@@ -296,21 +294,25 @@ public function send_get ($url = null, $token = null, $params = null)
* @param string $token The session token returned by ILSWS
* @param string $query_json JSON containing the required query elements
* @param string $query_type The query type: POST or PUT
+ * @param array $options Associative array of options (role, client_id, header)
* @return object $response Associative array containing the response from ILSWS
*/
- public function send_query ($url = null, $token = null, $query_json = null, $query_type = null, $role = 'PATRON', $client_id = '', $header = '')
+ public function send_query ($url = null, $token = null, $query_json = null, $query_type = null, $options = [])
{
$this->validate('url', $url, 'u');
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('query_type', $query_type, 'v:POST|PUT|DELETE');
- $this->validate('header', $header, 's:40');
- $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
- if ( $client_id ) {
- $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
- } else {
- $client_id = $this->config['ilsws']['client_id'];
+ if ( !empty($options) ) {
+ $role = !empty($options['role']) ? $options['role'] : 'PATRON';
+ $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
+
+ $client_id = !empty($options['client_id']) ? $options['client_id'] : $this->config['ilsws']['client_id'];
+ $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
+
+ $header = !empty($options['header']) ? $options['header'] : '';
+ $this->validate('header', $header, 's:40');
}
if ( $query_json ) {
@@ -375,7 +377,6 @@ public function send_query ($url = null, $token = null, $query_json = null, $que
} catch (APIException $e) {
echo $e->errorMessage($this->error, $this->code), "\n";
- exit(1);
}
return json_decode($json, true);
@@ -636,11 +637,13 @@ public function transit_item ($token = null, $item_key = null, $new_library = nu
];
$json = json_encode($data);
- // Add header required for this API endpoint
- $header = "SD-Working-LibraryID: $working_library";
+ // Add header and role required for this API endpoint
+ $options = [];
+ $options['header'] = "SD-Working-LibraryID: $working_library";
+ $options['role'] = 'STAFF';
// Describe patron register function
- $response = $this->send_query("$this->base_url/circulation/transit", $token, $json, 'POST', 'STAFF', $header);
+ $response = $this->send_query("$this->base_url/circulation/transit", $token, $json, 'POST', $options);
return $response;
}
@@ -1288,23 +1291,25 @@ public function delete_patron ($token = null, $patron_key = null)
* @param string $token The session token returned by ILSWS
* @param string $json JSON containing either currentPassword and newPassword or
* resetPasswordToken and newPassword
+ * @param array $options Associative array of options (role, client_id)
* @return object Associative array containing response from ILSWS
*/
- public function change_patron_password ($token = null, $json = null, $role = 'PATRON', $client_id = '')
+ public function change_patron_password ($token = null, $json = null, $options = [])
{
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('json', $json, 'j');
- $this->validate('role', $role, 'v:PATRON|STAFF|GUEST');
- if ( $client_id ) {
- $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
- } else {
- $client_id = $this->config['ilsws']['client_id'];
+ if ( !empty($options) ) {
+ $options['client_id'] = !empty($options['client_id']) ? $options['client_id'] : $client_id = $this->config['ilsws']['client_id'];
+ $this->validate('client_id', $options['client_id'], 'r:#^[A-Za-z]{4,20}$#');
+
+ $options['role'] = !empty($options['role']) ? $options['role'] : 'PATRON';
+ $this->validate('role', $options['role'], 'v:PATRON|STAFF|GUEST');
}
- return $this->send_query("$this->base_url/user/patron/changeMyPassword", $token, $json, 'POST', $role, $client_id);
+ return $this->send_query("$this->base_url/user/patron/changeMyPassword", $token, $json, 'POST', $options);
}
/**
@@ -2268,21 +2273,27 @@ private function create_register_json ($patron, $token = null, $addr_num = 1)
* @param object $patron Associative array containing patron data
* @param string $token The session token returned by ILSWS
* @param integer $addr_num Optional Address number to update (1, 2, or 3, defaults to 1)
- * @param string $template Full path to email template to use
+ * @param array $options Associative array of options (role, client_id, template, subject)
* @return object $response Associative array containing response from ILSWS
*/
- public function register_patron ($patron, $token = null, $addr_num = null, $role = 'PATRON', $client_id = '', $template = '', $subject = '')
+ public function register_patron ($patron, $token = null, $addr_num = null, $options = [])
{
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('addr_num', $addr_num, 'r:#^[123]{1}$#');
- $this->validate('template', $template, 'r:#^([a-zA-Z0-9]{1,40})(\.)(html|text)(\.)(twig)$#');
- $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
- if ( $client_id ) {
+ if ( !empty($options) ) {
+ $role = !empty($options['role']) ? $options['role'] : 'PATRON';
+ $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
+
+ $client_id = !empty($options['client_id']) ? $options['client_id'] : $this->config['ilsws']['client_id'];
$this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
- } else {
- $client_id = $this->config['ilsws']['client_id'];
+
+ $template = !empty($options['template']) ? $options['template'] : '';
+ $this->validate('template', $template, 'r:#^([a-zA-Z0-9]{1,40})(\.)(html|text)(\.)(twig)$#');
+
+ $subject = !empty($options['subject']) ? $options['subject'] : '';
+ $this->validate('subject', $subject, 's:20');
}
$response = [];
@@ -2334,7 +2345,10 @@ public function register_patron ($patron, $token = null, $addr_num = null, $role
}
// Send initial registration (and generate email)
- $response = $this->send_query("$this->base_url/user/patron", $token, $json, 'POST', $role, $client_id);
+ $options = [];
+ $options['role'] = $role;
+ $options['client_id'] = $client_id;
+ $response = $this->send_query("$this->base_url/user/patron", $token, $json, 'POST', $options);
if ( !empty($response['key']) ) {
$patron_key = $response['key'];
@@ -2346,14 +2360,12 @@ public function register_patron ($patron, $token = null, $addr_num = null, $role
$patron['barcode'] = $patron_key;
if ( ! $this->change_barcode($token, $patron_key, $patron_key) ) {
throw new Exception('Unable to set barcode to patron key');
- exit();
}
}
if ( !empty($patron['phoneList']) ) {
if ( ! $this->update_phone_list($patron['phoneList'], $token, $patron_key) ) {
throw new Exception('SMS phone list update failed');
- exit();
}
}
@@ -2363,7 +2375,6 @@ public function register_patron ($patron, $token = null, $addr_num = null, $role
}
if ( ! $this->email_template($patron, $this->config['smtp']['smtp_from'], $patron['EMAIL'], $subject, $template) ) {
throw new Exception('Email to patron failed');
- exit();
}
}
}
@@ -2409,7 +2420,6 @@ public function update_patron ($patron, $token = null, $patron_key = null, $addr
if ( !empty($patron['phoneList']) ) {
if ( ! $this->update_phone_list($patron['phoneList'], $token, $patron_key) ) {
throw new Exception('SMS phone list update failed');
- exit;
}
}
diff --git a/test/register_patron.php b/test/register_patron.php
index edc1996..6ac6084 100644
--- a/test/register_patron.php
+++ b/test/register_patron.php
@@ -43,11 +43,14 @@
];
$addr_num = 1;
-$template = 'registration_email.html.twig';
-$role = 'STAFF'; // Used in the SD-Preferred-Role HTTP header
-$client_id = 'QUIPU'; // Used in the x-sirs-clientID HTTP header
-$response = $ilsws->register_patron($patron, $token, $addr_num, $role, $client_id, $template, 'Waffles are good');
+$options = [];
+$options['template'] = 'registration_email.html.twig';
+$options['role'] = 'STAFF'; // Used in the SD-Preferred-Role HTTP header
+$options['client_id'] = 'QUIPU'; // Used in the x-sirs-clientID HTTP header
+$options['subject'] = 'Waffles are good';
+
+$response = $ilsws->register_patron($patron, $token, $addr_num, $options);
print json_encode($response, JSON_PRETTY_PRINT) . "\n";
// EOF
diff --git a/test/register_staff.php b/test/register_staff.php
index 006c89c..eaec586 100644
--- a/test/register_staff.php
+++ b/test/register_staff.php
@@ -43,8 +43,12 @@
];
$addr_num = 1;
-$role = 'STAFF';
-$response = $ilsws->register_patron($patron, $token, $addr_num, $role);
+
+$options = [];
+$options['role'] = 'STAFF';
+$options['client_id'] = 'QUIPU';
+
+$response = $ilsws->register_patron($patron, $token, $addr_num, $options);
print json_encode($response, JSON_PRETTY_PRINT) . "\n";
// EOF
From 35a78e7a07740f16f83dfd9f6b9c64de2651fee4 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Thu, 22 Feb 2024 11:19:39 -0800
Subject: [PATCH 2/8] README.md edits
---
README.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 5424312..db5e0be 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ if presented with inappropriate inputs.
- authenticate_patron($token, $patron_id, $password)
- change_barcode($token, $patron_key, $patron_id)
- change_item_library($token, $item_key, $library)
-- change_patron_password($token, $json, $options)
+- change_patron_password($token, $json, $options)
Options array may include: role, client_id
- delete_patron($token, $patron_key)
- describe_bib($token)
@@ -69,15 +69,15 @@ or evaluating data from the Symphony system.
- get_patron_checkouts($token, $patron_key, $include_fields)
- get_patron_indexes($token)
- prepare_search($terms)
-- register_patron($patron, $token, $addr_num, $options)
+- register_patron($patron, $token, $addr_num, $options)
Options array may include: role, client_id, template, subject
-- reset_patron_password($token, $patron_id, $url, $email)
+- reset_patron_password($token, $patron_id, $url, $email)
Optional: email
- search_authenticate($token, $index, $search, $password)
-- search_bib($token, $index, $value, $params)
+- search_bib($token, $index, $value, $params)
Params array may include: q, ct, rw, j, includeFields
- update_patron($patron, $token, $patron_key, $addr_num)
-- update_patron_activeid($token, $patron_key, $patron_id, $option)
+- update_patron_activeid($token, $patron_key, $patron_id, $option)
Option may be: a, i, d
- update_phone_list($phone_list, $token, $patron_key)
From 0901b7853821d30a11e9d90c86664b60b7a9d2f2 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Thu, 22 Feb 2024 14:01:21 -0800
Subject: [PATCH 3/8] Remove warnings and pass credentials used for initial
registrations through to other function calls
---
README.md | 6 +-
src/Libilsws.php | 167 +++++++++++++++++++--------------------
test/register_patron.php | 3 +-
test/register_staff.php | 2 +-
4 files changed, 88 insertions(+), 90 deletions(-)
diff --git a/README.md b/README.md
index db5e0be..9d7eed8 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,8 @@ they valididate all inputs and will throw exceptions
if presented with inappropriate inputs.
- authenticate_patron($token, $patron_id, $password)
-- change_barcode($token, $patron_key, $patron_id)
+- change_barcode($token, $patron_key, $patron_id, $options)
+ Options array may include: role, client_id
- change_item_library($token, $item_key, $library)
- change_patron_password($token, $json, $options)
Options array may include: role, client_id
@@ -79,7 +80,8 @@ or evaluating data from the Symphony system.
- update_patron($patron, $token, $patron_key, $addr_num)
- update_patron_activeid($token, $patron_key, $patron_id, $option)
Option may be: a, i, d
-- update_phone_list($phone_list, $token, $patron_key)
+- update_phone_list($phone_list, $token, $patron_key, $options)
+ Options array may include: role, client_id
## Date and Telephone Number Formats
For the convenience of developers, the code library accepts
diff --git a/src/Libilsws.php b/src/Libilsws.php
index ad47771..0129052 100644
--- a/src/Libilsws.php
+++ b/src/Libilsws.php
@@ -56,13 +56,13 @@ public function errorMessage ($error = "", $code = 0)
$err_message = json_decode($error, true);
if ( json_last_error() === JSON_ERROR_NONE ) {
- if ( ! empty($err_message['messageList'][0]['message']) ) {
+ if ( !empty($err_message['messageList'][0]['message']) ) {
$error = $err_message['messageList'][0]['message'];
$message .= ": $error";
}
}
- if ( ! $message ) {
+ if ( !$message ) {
$message = "HTTP $code: $error";
}
@@ -132,7 +132,7 @@ public function __construct($yaml_file)
private function validate ($param, $value, $rule)
{
- if ( ! $this->dh->validate($value, $rule) ) {
+ if ( !$this->dh->validate($value, $rule) ) {
throw new Exception ("Invalid $param: \"$value\" (rule: '$rule')");
}
@@ -182,7 +182,7 @@ public function connect ()
error_log("DEBUG_CONNECT HTTP $this->code: $json", 0);
}
- if ( ! preg_match('/^2\d\d$/', $this->code) ) {
+ if ( !preg_match('/^2\d\d$/', $this->code) ) {
$obfuscated_url = $this->base_url . "/$action?" . preg_replace('/(password)=(.*?([;]|$))/', '${1}=***', "$params");
$this->error = "Connect failure: $obfuscated_url: " . curl_error($ch);
throw new APIException($this->error);
@@ -216,10 +216,10 @@ public function send_get ($url = null, $token = null, $params = null)
$this->validate('url', $url, 'u');
// Encode the query parameters, as they will be sent in the URL
- if ( ! empty($params) ) {
+ if ( !empty($params) ) {
$url .= "?";
foreach ($params as $key => $value) {
- if ( ! empty($params[$key]) ) {
+ if ( !empty($params[$key]) ) {
$url .= "$key=" . urlencode($params[$key]) . '&';
}
}
@@ -271,7 +271,7 @@ public function send_get ($url = null, $token = null, $params = null)
// Check for errors
if ( $this->code != 200 ) {
$this->error = curl_error($ch);
- if ( ! $this->error ) {
+ if ( !$this->error ) {
$this->error = $json;
}
throw new APIException($this->error);
@@ -304,16 +304,14 @@ public function send_query ($url = null, $token = null, $query_json = null, $que
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('query_type', $query_type, 'v:POST|PUT|DELETE');
- if ( !empty($options) ) {
- $role = !empty($options['role']) ? $options['role'] : 'PATRON';
- $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
+ $role = !empty($options['role']) ? $options['role'] : 'PATRON';
+ $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
- $client_id = !empty($options['client_id']) ? $options['client_id'] : $this->config['ilsws']['client_id'];
- $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
+ $client_id = !empty($options['client_id']) ? $options['client_id'] : $this->config['ilsws']['client_id'];
+ $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
- $header = !empty($options['header']) ? $options['header'] : '';
- $this->validate('header', $header, 's:40');
- }
+ $header = !empty($options['header']) ? $options['header'] : '';
+ $this->validate('header', $header, 's:40');
if ( $query_json ) {
$this->validate('query_json', $query_json, 'j');
@@ -364,9 +362,9 @@ public function send_query ($url = null, $token = null, $query_json = null, $que
}
// Check for errors
- if ( ! preg_match('/^2\d\d$/', $this->code) ) {
+ if ( !preg_match('/^2\d\d$/', $this->code) ) {
$this->error = curl_error($ch);
- if ( ! $this->error ) {
+ if ( !$this->error ) {
$this->error = $json;
}
throw new APIException($this->error);
@@ -416,9 +414,9 @@ function flatten_call ($token, $call)
foreach ($call['fields'] as $field => $value) {
- if ( ! is_array($value) ) {
+ if ( !is_array($value) ) {
$item_list[$field] = $value;
- } elseif ( ! empty($call['fields'][$field]['key']) ) {
+ } elseif ( !empty($call['fields'][$field]['key']) ) {
$item_list[$field] = $call['fields'][$field]['key'];
} elseif ( $field == 'itemList' ) {
foreach ($call['fields']['itemList'] as $item) {
@@ -453,7 +451,7 @@ private function flatten_item ($token, $record)
$item['itemCircInfo'] = $this->get_item_circ_info($token, $record['fields']['itemCircInfo']['key']);
} elseif ( $key === 'holdRecordList' ) {
for ($i = 0; $i < count($record['fields']['holdRecordList']); $i++) {
- if ( ! empty($record['fields']['holdRecordList'][$i]['key']) ) {
+ if ( !empty($record['fields']['holdRecordList'][$i]['key']) ) {
$item['holdRecordList'][$i] = $this->get_hold($token, $record['fields']['holdRecordList'][$i]['key']);
}
}
@@ -461,7 +459,7 @@ private function flatten_item ($token, $record)
$item['price'] = $record['fields']['price']['currencyCode']
. ' '
. $record['fields']['price']['amount'];
- } elseif ( ! empty($record['fields'][$key]['key']) ) {
+ } elseif ( !empty($record['fields'][$key]['key']) ) {
$item[$key] = $record['fields'][$key]['key'];
} else {
$item[$key] = $value;
@@ -514,7 +512,7 @@ private function flatten_bib ($token, $record)
$bib['holdRecordList'][$i] = $this->get_hold($token, $record['holdRecordList'][$i]['key']);
}
- } elseif ( ! empty($record[$key]['key']) ) {
+ } elseif ( !empty($record[$key]['key']) ) {
$bib[$key] = $record[$key]['key'];
@@ -584,7 +582,7 @@ public function get_patron_checkouts ($token = null, $patron_key = null, $includ
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('patron_key', $patron_key, 'r:#^d{1,6}$#');
- if (! $include_fields) {
+ if (!$include_fields) {
$include_fields = 'item,library';
}
@@ -747,7 +745,7 @@ private function validate_bib_fields ($token = null, $field_list = '')
$diff_fields = array_diff($input_fields, $bib_fields);
$call_fields = [];
- if ( ! empty($diff_fields) ) {
+ if ( !empty($diff_fields) ) {
$describe = $this->send_get("$this->base_url/catalog/call/describe", $token, []);
foreach ($describe['fields'] as $field) {
array_push($call_fields, $field['name']);
@@ -761,7 +759,7 @@ private function validate_bib_fields ($token = null, $field_list = '')
$diff_fields = array_diff($diff_fields, $call_fields);
$item_fields = [];
- if ( ! empty($diff_fields) ) {
+ if ( !empty($diff_fields) ) {
$describe = $this->send_get("$this->base_url/catalog/item/describe", $token, []);
foreach ($describe['fields'] as $field) {
array_push($item_fields, $field['name']);
@@ -775,9 +773,9 @@ private function validate_bib_fields ($token = null, $field_list = '')
*/
$diff_fields = array_diff($diff_fields, $item_fields);
- if ( ! empty($diff_fields) ) {
+ if ( !empty($diff_fields) ) {
foreach ($diff_fields as $field) {
- if ( ! preg_match("/^\d{3}(_[a-zA-Z0-9]{1})*$/", $field) ) {
+ if ( !preg_match("/^\d{3}(_[a-zA-Z0-9]{1})*$/", $field) ) {
throw new Exception ("Invalid field \"$field\" in includeFields");
}
}
@@ -803,14 +801,14 @@ public function get_bib_marc ($token = null, $bib_key = null)
$response = $this->send_get("$this->base_url/catalog/bib/key/$bib_key", $token, []);
- if ( ! empty($response['fields']['bib']) ) {
+ if ( !empty($response['fields']['bib']) ) {
$bib['key'] = $response['key'];
foreach ($response['fields']['bib'] as $marc_key => $marc_value) {
- if ( ! is_array($marc_value) ) {
+ if ( !is_array($marc_value) ) {
$bib[$marc_key] = $marc_value;
} else {
foreach ($marc_value as $tag) {
- if ( ! empty($tag['tag']) ) {
+ if ( !empty($tag['tag']) ) {
foreach ($tag['subfields'] as $subfield) {
if ( $subfield['code'] == '_' ) {
$bib[$tag['tag']] = $subfield['data'];
@@ -844,7 +842,7 @@ public function get_bib_circ_info ($token = null, $bib_key = null)
$response = $this->send_get("$this->base_url/circulation/bibCircInfo/key/$bib_key", $token, []);
- if ( ! empty($response['fields']) ) {
+ if ( !empty($response['fields']) ) {
foreach ($response['fields'] as $field => $value) {
$stats[$field] = $value;
}
@@ -880,7 +878,7 @@ public function get_bib ($token = null, $bib_key = null, $field_list = '')
$response = $this->send_get("$this->base_url/catalog/bib/key/$bib_key?includeFields=" . $field_list, $token, []);
- if ( ! empty($response['fields']) ) {
+ if ( !empty($response['fields']) ) {
// Flatten the structure to a simple hash
$temp = $this->flatten_bib($token, $response['fields']);
@@ -889,7 +887,7 @@ public function get_bib ($token = null, $bib_key = null, $field_list = '')
$bib['key'] = $response['key'];
foreach ($fields as $field) {
- if ( ! empty($temp[$field]) ) {
+ if ( !empty($temp[$field]) ) {
$bib[$field] = $temp[$field];
}
}
@@ -915,9 +913,9 @@ public function get_item_circ_info ($token = null, $item_key = null)
$response = $this->send_get("$this->base_url/circulation/itemCircInfo/key/$item_key", $token, []);
- if ( ! empty($response['fields']) ) {
+ if ( !empty($response['fields']) ) {
foreach ($response['fields'] as $field => $value) {
- if ( ! empty($response['fields'][$field]['key']) ) {
+ if ( !empty($response['fields'][$field]['key']) ) {
$stats[$field] = $response['fields'][$field]['key'];
} else {
$stats[$field] = $value;
@@ -954,7 +952,7 @@ public function get_item ($token = null, $item_key = null, $field_list = '*')
$item = $this->send_get("$this->base_url/catalog/item/key/$item_key?includeFields=$field_list", $token, []);
- if ( ! empty($item['fields']) ) {
+ if ( !empty($item['fields']) ) {
$item = $this->flatten_item($token, $item);
}
@@ -973,10 +971,10 @@ private function flatten_hold ($record)
{
$hold = [];
- if ( ! empty($record['fields']) ) {
+ if ( !empty($record['fields']) ) {
$hold['key'] = $record['key'];
foreach ($record['fields'] as $field => $value) {
- if ( ! empty($record['fields'][$field]['key']) ) {
+ if ( !empty($record['fields'][$field]['key']) ) {
$hold[$field] = $record['fields'][$field]['key'];
} else {
$hold[$field] = $value;
@@ -1004,7 +1002,7 @@ public function get_hold ($token = null, $hold_key = null)
$hold = $this->send_get("$this->base_url/circulation/holdRecord/key/$hold_key", $token, []);
- if ( ! empty($hold['fields']) ) {
+ if ( !empty($hold['fields']) ) {
$hold = $this->flatten_hold($hold);
}
@@ -1035,7 +1033,7 @@ public function get_call_number ($token = null, $call_key = null, $field_list =
$call = $this->send_get("$this->base_url/catalog/call/key/$call_key?includeFields=$field_list", $token);
- if ( ! empty($call['fields']) ) {
+ if ( !empty($call['fields']) ) {
$call = $this->flatten_call($token, $call);
}
@@ -1092,7 +1090,7 @@ public function get_library_paging_list ($token = null, $library_key = null)
$include_fields = 'pullList{holdRecord{holdType,status,pickupLibrary},item{call{bib{author,title},callNumber,sortCallNumber},barcode,currentLocation{description}itemType}}';
$response = $this->send_get("$this->base_url/circulation/holdItemPullList/key/$library_key", $token, ['includeFields' => $include_fields]);
- if ( ! empty($response['fields']['pullList']) ) {
+ if ( !empty($response['fields']['pullList']) ) {
foreach ($response['fields']['pullList'] as $hold) {
$record = [];
@@ -1238,18 +1236,18 @@ public function search_bib ($token = null, $index = null, $value = null, $params
$response = $this->send_get("$this->base_url/catalog/bib/search", $token, $params);
$records = [];
- if ( ! empty($response['totalResults']) && $response['totalResults'] > 0 ) {
+ if ( !empty($response['totalResults']) && $response['totalResults'] > 0 ) {
for ($i = 0; $i < count($response['result']); $i++) {
- if ( ! is_null($response['result'][$i]) ) {
+ if ( !is_null($response['result'][$i]) ) {
$bib = $this->flatten_bib($token, $response['result'][$i]['fields']);
$bib['key'] = $response['result'][$i]['key'];
$filtered_bib = [];
foreach ($fields as $field) {
- if ( ! empty($bib[$field]) ) {
+ if ( !empty($bib[$field]) ) {
$filtered_bib[$field] = $bib[$field];
}
}
@@ -1800,13 +1798,13 @@ private function get_profile ($patron)
{
// Look in all the places we might find an incoming profile
$profile = '';
- if (! empty($patron['profile']) ) {
+ if (!empty($patron['profile']) ) {
$profile = $patron['profile'];
- } elseif ( ! empty($this->config['symphony']['new_fields']['alias'])
- && ! empty($patron[$this->config['symphony']['new_fields']['alias']]) ) {
+ } elseif ( !empty($this->config['symphony']['new_fields']['alias'])
+ && !empty($patron[$this->config['symphony']['new_fields']['alias']]) ) {
$profile = $patron[$this->config['symphony']['new_fields']['alias']];
- } elseif ( ! empty($this->config['symphony']['overlay_fields']['alias'])
- && ! empty($patron[$this->config['symphony']['overlay_fields']['alias']]) ) {
+ } elseif ( !empty($this->config['symphony']['overlay_fields']['alias'])
+ && !empty($patron[$this->config['symphony']['overlay_fields']['alias']]) ) {
$profile = $patron[$this->config['symphony']['overlay_fields']['alias']];
}
@@ -1817,13 +1815,13 @@ private function get_profile ($patron)
// Check everywhere we might find a birth date
$dob = '';
- if ( ! empty($patron['birthDate']) ) {
+ if ( !empty($patron['birthDate']) ) {
$dob = $this->create_field_date('birthDate', $patron['birthDate']);
- } elseif ( ! empty($this->config['symphony']['new_fields']['birthDate']['alias'])
- && ! empty($patron[$this->config['symphony']['new_fields']['birthDate']['alias']]) ) {
+ } elseif ( !empty($this->config['symphony']['new_fields']['birthDate']['alias'])
+ && !empty($patron[$this->config['symphony']['new_fields']['birthDate']['alias']]) ) {
$dob = $this->create_field_date('birthDate', $patron[$this->config['symphony']['new_fields']['birthDate']['alias']]);
- } elseif ( ! empty($this->config['symphony']['overlay_fields']['birthDate']['alias'])
- && ! empty($patron[$this->config['symphony']['overlay_fields']['birthDate']['alias']]) ) {
+ } elseif ( !empty($this->config['symphony']['overlay_fields']['birthDate']['alias'])
+ && !empty($patron[$this->config['symphony']['overlay_fields']['birthDate']['alias']]) ) {
$dob = $this->create_field_date('birthDate', $patron[$this->config['symphony']['overlay_fields']['birthDate']['alias']]);
}
@@ -1838,7 +1836,7 @@ private function get_profile ($patron)
}
// Check if the age fits into a range
- if ( $age && ! empty($this->config['symphony']['age_ranges']) ) {
+ if ( $age && !empty($this->config['symphony']['age_ranges']) ) {
$ranges = $this->config['symphony']['age_ranges'];
foreach ($ranges as $range => $value) {
@@ -1887,17 +1885,17 @@ private function check_fields ($patron, $fields)
foreach ($fields as $field => $value) {
// Assign default values to empty fields, where appropriate
- if ( empty($patron[$field]) && ! empty($fields[$field]['default']) ) {
+ if ( empty($patron[$field]) && !empty($fields[$field]['default']) ) {
$patron[$field] = $fields[$field]['default'];
}
// Check for missing required fields
- if ( empty($patron[$field]) && ! empty($fields[$field]['required']) && $fields[$field]['required'] === 'true' ) {
+ if ( empty($patron[$field]) && !empty($fields[$field]['required']) && $fields[$field]['required'] === 'true' ) {
throw new Exception ("The $field field is required");
}
// Validate
- if ( ! empty($patron[$field]) && ! empty($fields[$field]['validation']) ) {
+ if ( !empty($patron[$field]) && !empty($fields[$field]['validation']) ) {
$this->validate($field, $patron[$field], $fields[$field]['validation']);
}
}
@@ -2064,7 +2062,7 @@ private function create_field_date ($name, $value)
}
}
- if ( ! $date ) {
+ if ( !$date ) {
throw new Exception ("Invalid date format: \"$value\" in $name field");
}
@@ -2186,17 +2184,17 @@ private function create_field_address ($field, $field_value, $fields, $addr_num)
foreach ($fields as $subfield => $value) {
// Check if the data is coming in with a different field name (alias)
- if ( empty($patron[$subfield]) && ! empty($fields[$field][$subfield]['alias']) ) {
+ if ( empty($patron[$subfield]) && !empty($fields[$field][$subfield]['alias']) ) {
$patron[$subfield] = $patron[$fields[$field][$subfield]['alias']];
}
// Assign default values where appropriate
- if ( empty($patron[$subfield]) && ! empty($fields[$field][$subfield]['default']) ) {
+ if ( empty($patron[$subfield]) && !empty($fields[$field][$subfield]['default']) ) {
$patron[$subfield] = $fields[$field][$subfield]['default'];
}
// Check for missing required fields
- if ( empty($patron[$subfield]) && ! empty($fields[$subfield]['required']) && boolval($fields[$subfield]['required']) ) {
+ if ( empty($patron[$subfield]) && !empty($fields[$subfield]['required']) && boolval($fields[$subfield]['required']) ) {
throw new Exception ("The $field $subfield field is required");
}
@@ -2282,19 +2280,17 @@ public function register_patron ($patron, $token = null, $addr_num = null, $opti
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('addr_num', $addr_num, 'r:#^[123]{1}$#');
- if ( !empty($options) ) {
- $role = !empty($options['role']) ? $options['role'] : 'PATRON';
- $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
+ $role = !empty($options['role']) ? $options['role'] : 'PATRON';
+ $this->validate('role', $role, 'v:STAFF|PATRON|GUEST');
- $client_id = !empty($options['client_id']) ? $options['client_id'] : $this->config['ilsws']['client_id'];
- $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
+ $client_id = !empty($options['client_id']) ? $options['client_id'] : $this->config['ilsws']['client_id'];
+ $this->validate('client_id', $client_id, 'r:#^[A-Za-z]{4,20}$#');
- $template = !empty($options['template']) ? $options['template'] : '';
- $this->validate('template', $template, 'r:#^([a-zA-Z0-9]{1,40})(\.)(html|text)(\.)(twig)$#');
+ $template = !empty($options['template']) ? $options['template'] : '';
+ $this->validate('template', $template, 'r:#^([a-zA-Z0-9]{1,40})(\.)(html|text)(\.)(twig)$#');
- $subject = !empty($options['subject']) ? $options['subject'] : '';
- $this->validate('subject', $subject, 's:20');
- }
+ $subject = !empty($options['subject']) ? $options['subject'] : '';
+ $this->validate('subject', $subject, 's:20');
$response = [];
@@ -2354,17 +2350,17 @@ public function register_patron ($patron, $token = null, $addr_num = null, $opti
$patron_key = $response['key'];
// If the barcode doesn't look like a real 14-digit barcode then change it to the patron key
- if ( !preg_match('/^\d{14}$/', $patron['barcode']) ) {
+ if ( empty($patron['barcode']) || !preg_match('/^\d{14}$/', $patron['barcode']) ) {
// Assign the patron_key from the initial registration to the update array
$patron['barcode'] = $patron_key;
- if ( ! $this->change_barcode($token, $patron_key, $patron_key) ) {
+ if ( !$this->change_barcode($token, $patron_key, $patron_key, $options) ) {
throw new Exception('Unable to set barcode to patron key');
}
}
if ( !empty($patron['phoneList']) ) {
- if ( ! $this->update_phone_list($patron['phoneList'], $token, $patron_key) ) {
+ if ( !$this->update_phone_list($patron['phoneList'], $token, $patron_key, $options) ) {
throw new Exception('SMS phone list update failed');
}
}
@@ -2373,7 +2369,7 @@ public function register_patron ($patron, $token = null, $addr_num = null, $opti
if ( !$subject ) {
$subject = !empty($this->config['smtp']['smtp_default_subject']) ? $this->config['smtp']['smtp_default_subject'] : '';
}
- if ( ! $this->email_template($patron, $this->config['smtp']['smtp_from'], $patron['EMAIL'], $subject, $template) ) {
+ if ( !$this->email_template($patron, $this->config['smtp']['smtp_from'], $patron['EMAIL'], $subject, $template) ) {
throw new Exception('Email to patron failed');
}
}
@@ -2418,7 +2414,7 @@ public function update_patron ($patron, $token = null, $patron_key = null, $addr
$response = $this->send_query("$this->base_url/user/patron/key/$patron_key", $token, $json, 'PUT');
if ( !empty($patron['phoneList']) ) {
- if ( ! $this->update_phone_list($patron['phoneList'], $token, $patron_key) ) {
+ if ( !$this->update_phone_list($patron['phoneList'], $token, $patron_key) ) {
throw new Exception('SMS phone list update failed');
}
}
@@ -2460,7 +2456,7 @@ public function update_patron_activeid ($token = null, $patron_key = null, $patr
if ( $res ) {
if ( $option == 'a' ) {
- if ( ! empty($res['fields']['customInformation']) ) {
+ if ( !empty($res['fields']['customInformation']) ) {
$custom = $res['fields']['customInformation'];
for ( $i = 0; $i < count($custom); $i++ ) {
if ( $custom[$i]['fields']['code']['key'] == 'ACTIVEID' && $custom[$i]['fields']['data'] ) {
@@ -2473,7 +2469,7 @@ public function update_patron_activeid ($token = null, $patron_key = null, $patr
} elseif ( $option == 'i' ) {
- if ( ! empty($res['fields']['customInformation']) ) {
+ if ( !empty($res['fields']['customInformation']) ) {
$custom = $res['fields']['customInformation'];
for ( $i = 0; $i < count($custom); $i++ ) {
if ( $custom[$i]['fields']['code']['key'] == 'INACTVID' && $custom[$i]['fields']['data'] ) {
@@ -2486,7 +2482,7 @@ public function update_patron_activeid ($token = null, $patron_key = null, $patr
} elseif ( $option == 'd' ) {
- if ( ! empty($res['fields']['customInformation']) ) {
+ if ( !empty($res['fields']['customInformation']) ) {
$custom = $res['fields']['customInformation'];
for ( $i = 0; $i < count($custom); $i++ ) {
$fields = array('ACTIVEID','INACTVID','PREV_ID','PREV_ID2','STUDENT_ID');
@@ -2582,7 +2578,7 @@ private function get_field_desc ($token, $name)
* @return integer $return_code 1 for success, 0 for failure
*/
- public function change_barcode ($token = null, $patron_key = null, $patron_id = null)
+ public function change_barcode ($token = null, $patron_key = null, $patron_id = null, $options = [])
{
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('patron_key', $patron_key, 'r:#^d{1,6}$#');
@@ -2594,10 +2590,10 @@ public function change_barcode ($token = null, $patron_key = null, $patron_id =
$new['fields']['barcode'] = $patron_id;
$json = json_encode($new, JSON_PRETTY_PRINT);
- $response = $this->send_query($this->base_url . "/user/patron/key/$patron_key", $token, $json, 'PUT');
+ $response = $this->send_query($this->base_url . "/user/patron/key/$patron_key", $token, $json, 'PUT', $options);
$return_code = 0;
- if ( !empty($response['fields']['barcode']) && $response['fields']['barcode'] === $patron_id ) {
+ if ( !empty($response['fields']['barcode']) && $response['fields']['barcode'] == $patron_id ) {
$return_code = 1;
}
@@ -2613,7 +2609,7 @@ public function change_barcode ($token = null, $patron_key = null, $patron_id =
* @return integer $return_code 1 for success, 0 for failure
*/
- public function update_phone_list ($phone_list, $token = null, $patron_key = null)
+ public function update_phone_list ($phone_list, $token = null, $patron_key = null, $options = [])
{
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('patron_key', $patron_key, 'r:#^d{1,6}$#');
@@ -2625,7 +2621,8 @@ public function update_phone_list ($phone_list, $token = null, $patron_key = nul
array_push($new['fields']['phoneList'], $this->create_field_phone($patron_key, $phone_list));
$json = json_encode($new, JSON_PRETTY_PRINT);
- $response = $this->send_query($this->base_url . "/user/patron/key/$patron_key", $token, $json, 'PUT');
+ $response = $this->send_query($this->base_url . "/user/patron/key/$patron_key", $token, $json, 'PUT', $options);
+ print_r($response);
$return_code = 0;
if ( !empty($response['key']) && $response['key'] === $patron_key ) {
diff --git a/test/register_patron.php b/test/register_patron.php
index 6ac6084..27143be 100644
--- a/test/register_patron.php
+++ b/test/register_patron.php
@@ -28,7 +28,6 @@
'pin' => 'Waffles125',
'postal_code' => '97209',
'profile' => 'ONLINE',
- 'patron_id' => '99999999998',
'street' => '925 NW Hoyt St Apt 406',
'telephone' => '215-534-6821',
'sms_phone' => [
@@ -48,7 +47,7 @@
$options['template'] = 'registration_email.html.twig';
$options['role'] = 'STAFF'; // Used in the SD-Preferred-Role HTTP header
$options['client_id'] = 'QUIPU'; // Used in the x-sirs-clientID HTTP header
-$options['subject'] = 'Waffles are good';
+$options['subject'] = 'Welcome to our library!';
$response = $ilsws->register_patron($patron, $token, $addr_num, $options);
print json_encode($response, JSON_PRETTY_PRINT) . "\n";
diff --git a/test/register_staff.php b/test/register_staff.php
index eaec586..a0e3baf 100644
--- a/test/register_staff.php
+++ b/test/register_staff.php
@@ -17,7 +17,7 @@
'city_state' => 'Portland, OR',
'county' => '0_MULT',
'profile' => '0_MULT',
- 'patron_id' => '99999999999996',
+ 'patron_id' => '99999999999919',
'email' => 'johnchouser@gmail.com',
'firstName' => 'Bogus',
'friends_notices' => 'YES',
From ce4a34fdccab14e0ad8f5973eb8cec42f305d246 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Thu, 22 Feb 2024 14:18:17 -0800
Subject: [PATCH 4/8] Code efficiency
---
src/Libilsws.php | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/Libilsws.php b/src/Libilsws.php
index 0129052..576f12b 100644
--- a/src/Libilsws.php
+++ b/src/Libilsws.php
@@ -1299,14 +1299,6 @@ public function change_patron_password ($token = null, $json = null, $options =
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('json', $json, 'j');
- if ( !empty($options) ) {
- $options['client_id'] = !empty($options['client_id']) ? $options['client_id'] : $client_id = $this->config['ilsws']['client_id'];
- $this->validate('client_id', $options['client_id'], 'r:#^[A-Za-z]{4,20}$#');
-
- $options['role'] = !empty($options['role']) ? $options['role'] : 'PATRON';
- $this->validate('role', $options['role'], 'v:PATRON|STAFF|GUEST');
- }
-
return $this->send_query("$this->base_url/user/patron/changeMyPassword", $token, $json, 'POST', $options);
}
From 1c81ee074752c09558813c28082d3755975fa519 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Mon, 26 Feb 2024 14:07:27 -0800
Subject: [PATCH 5/8] Grouped functions by module
---
src/Libilsws.php | 831 ++++++++++++++++++++++++-----------------------
1 file changed, 416 insertions(+), 415 deletions(-)
diff --git a/src/Libilsws.php b/src/Libilsws.php
index 576f12b..1eeed0b 100644
--- a/src/Libilsws.php
+++ b/src/Libilsws.php
@@ -4,9 +4,9 @@
/**
*
- * Multnomah County Library ILSWS API Support
- *
- * Copyright (c) 2022 Multnomah County (Oregon)
+ * Multnomah County Library
+ * SirsiDynix ILSWS API Support
+ * Copyright (c) 2024 Multnomah County (Oregon)
*
* John Houser
* john.houser@multco.us
@@ -82,16 +82,16 @@ class Libilsws
public $base_url;
// The ILSWS connection parameters and Symphony field configuration
- private $config;
+ public $config;
// Data handler instance
- private $dh;
+ public $dh;
// ILSWS patron field description information
- private $field_desc = [];
+ public $field_desc = [];
// Constructor for this class
- public function __construct($yaml_file)
+ public function __construct ($yaml_file)
{
$this->dh = new DataHandler();
@@ -115,6 +115,48 @@ public function __construct($yaml_file)
. $this->config['ilsws']['webapp'];
}
+ /**
+ * Validate call or item input fields using the API describe function
+ *
+ * @param string $token Session token returned by ILSWS
+ * @param string $field_list Comma-delimited list of fields to be validated
+ * @return object $response Object containing include list, index list,
+ * and array of include fields
+ */
+
+ private function validate_fields ($token = null, $type = null, $field_list = '')
+ {
+ $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('type', $type, 'v:item|call');
+
+ if ( $field_list != '*' ) {
+
+ // Convert the input fields to an array
+ $input_fields = preg_split('/[,{}]+/', $field_list, -1, PREG_SPLIT_NO_EMPTY);
+
+ // Get the fields described by the API
+ $fields = [];
+ $describe = $this->send_get("$this->base_url/catalog/$type/describe", $token, []);
+ for ($i = 0; $i < count($describe['fields']); $i++) {
+ array_push($fields, $describe['fields'][$i]['name']);
+ }
+ // Get the item fields as well, if we're validating a get_call field_list
+ if ( $type == 'call' ) {
+ $describe = $this->send_get("$this->base_url/catalog/item/describe", $token, []);
+ for ($i = 0; $i < count($describe['fields']); $i++) {
+ array_push($fields, $describe['fields'][$i]['name']);
+ }
+ }
+ $valid_list = implode('|', $fields);
+
+ foreach ($input_fields as $field) {
+ $this->validate('includeFields', $field, "v:$valid_list|*");
+ }
+ }
+
+ return 1;
+ }
+
/**
* Validation by rule, using datahandler/validate. If
* dataHandler/validate receives a null value, it will return
@@ -380,6 +422,24 @@ public function send_query ($url = null, $token = null, $query_json = null, $que
return json_decode($json, true);
}
+ /**
+ * Get policy returns a policy record
+ *
+ * @param string $token Session token returned by ILSWS
+ * @param string $policy_name Policy name for policy
+ * @param string $policy_key Policy key for policy
+ * @return object Associative array containing the response from ILSWS
+ */
+
+ public function get_policy ($token = null, $policy_name = null, $policy_key = null)
+ {
+ $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('policy_name', $policy_name, 'r:#^[A-Za-z0-9]{1,20}$#');
+ $this->validate('policy_key', $policy_key, 'r:#^[A-Za-z\- 0-9]{1,10}$#');
+
+ return $this->send_get("$this->base_url/policy/$policy_name/key/$policy_key", $token, []);
+ }
+
/**
* Flattens callList structure into simple hash
*
@@ -526,86 +586,141 @@ private function flatten_bib ($token, $record)
}
/**
- * Validate call or item input fields using the API describe function
- *
- * @param string $token Session token returned by ILSWS
- * @param string $field_list Comma-delimited list of fields to be validated
- * @return object $response Object containing include list, index list,
- * and array of include fields
+ * Get catalog search indexes
+ *
+ * @access public
+ * @param string $token Session token returned by ILSWS
+ * @return array $search_indexes Array of valid index names
*/
- private function validate_fields ($token = null, $type = null, $field_list = '')
+ public function get_catalog_indexes ($token = null)
{
+ $search_indexes = [];
+
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('type', $type, 'v:item|call');
- if ( $field_list != '*' ) {
+ $describe = $this->send_get("$this->base_url/catalog/bib/describe", $token, []);
- // Convert the input fields to an array
- $input_fields = preg_split('/[,{}]+/', $field_list, -1, PREG_SPLIT_NO_EMPTY);
+ foreach ($describe['searchIndexList'] as $index) {
+ array_push($search_indexes, $index['name']);
+ }
- // Get the fields described by the API
- $fields = [];
- $describe = $this->send_get("$this->base_url/catalog/$type/describe", $token, []);
- for ($i = 0; $i < count($describe['fields']); $i++) {
- array_push($fields, $describe['fields'][$i]['name']);
- }
- // Get the item fields as well, if we're validating a get_call field_list
- if ( $type == 'call' ) {
- $describe = $this->send_get("$this->base_url/catalog/item/describe", $token, []);
- for ($i = 0; $i < count($describe['fields']); $i++) {
- array_push($fields, $describe['fields'][$i]['name']);
- }
- }
- $valid_list = implode('|', $fields);
+ return $search_indexes;
+ }
- foreach ($input_fields as $field) {
- $this->validate('includeFields', $field, "v:$valid_list|*");
+ /**
+ * Get bib MARC data
+ *
+ * @param string $token Session token returned by ILSWS
+ * @param string $bib_key Bibliographic record key
+ * @return array Flat associative array with MARC record
+ */
+
+ public function get_bib_marc ($token = null, $bib_key = null)
+ {
+ $bib = [];
+
+ $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('bib_key', $bib_key, 'r:#^\d{1,8}$#');
+
+ $response = $this->send_get("$this->base_url/catalog/bib/key/$bib_key", $token, []);
+
+ if ( !empty($response['fields']['bib']) ) {
+ $bib['key'] = $response['key'];
+ foreach ($response['fields']['bib'] as $marc_key => $marc_value) {
+ if ( !is_array($marc_value) ) {
+ $bib[$marc_key] = $marc_value;
+ } else {
+ foreach ($marc_value as $tag) {
+ if ( !empty($tag['tag']) ) {
+ foreach ($tag['subfields'] as $subfield) {
+ if ( $subfield['code'] == '_' ) {
+ $bib[$tag['tag']] = $subfield['data'];
+ } else {
+ $bib[$tag['tag'] . ' ' . $tag['inds'] . ' _' . $subfield['code']] = $subfield['data'];
+ }
+ }
+ }
+ }
+ }
}
}
- return 1;
+ return $bib;
}
/**
- * Pulls list of items checked out to a patron
- *
- * @access public
- * @param string $token Session token returned by ILSWS
- * @param integer $patron_key Patron key of patron whose records we need to see
- * @param string $include_fields Optional
- * @return array $return Associative array of item keys and libraries
+ * Validate bib field names using the API describe functions
+ *
+ * @param string $token Session token returned by ILSWS
+ * @param string $field_list Comma-delimited list of fields to be validated
+ * @return object $response Object containing include list, array of
+ * valid_fields, array of filter fields, array
+ * of include fields, and index list.
*/
- public function get_patron_checkouts ($token = null, $patron_key = null, $include_fields = null)
+ private function validate_bib_fields ($token = null, $field_list = '')
{
+ $response = [];
+
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('patron_key', $patron_key, 'r:#^d{1,6}$#');
- if (!$include_fields) {
- $include_fields = 'item,library';
+ // Convert the input fields to an array
+ $input_fields = preg_split("/[,{}]/", $field_list, -1, PREG_SPLIT_NO_EMPTY);
+
+ // Get the fields to validate against
+ $bib_fields = [];
+ $describe = $this->send_get("$this->base_url/catalog/bib/describe", $token, []);
+ foreach ($describe['fields'] as $field) {
+ array_push($bib_fields, $field['name']);
}
+ array_push($bib_fields, '*');
+ array_push($bib_fields, 'key');
- $response = $this->send_get("$this->base_url/user/patron/key/$patron_key?includeFields=circRecordList{*}", $token, []);
- $fields = preg_split('/,/', $include_fields);
+ /**
+ * Check if there are unvalidated fields left after checking against
+ * bib fields. If there are, check against call fields, next.
+ */
+ $diff_fields = array_diff($input_fields, $bib_fields);
- $return = [];
- $i = 0;
- if (count($response) > 0) {
- foreach ($response['fields']['circRecordList'] as $item) {
- foreach ($fields as $field) {
- $data = $item['fields'][$field];
- if (is_array($data)) {
- $return[$i][$field] = $data['key'];
- } else {
- $return[$i][$field] = $data;
- }
+ $call_fields = [];
+ if ( !empty($diff_fields) ) {
+ $describe = $this->send_get("$this->base_url/catalog/call/describe", $token, []);
+ foreach ($describe['fields'] as $field) {
+ array_push($call_fields, $field['name']);
+ }
+ }
+
+ /**
+ * Check again. if there are still unvalidated fields after checking against
+ * the call fields, check against item fields.
+ */
+ $diff_fields = array_diff($diff_fields, $call_fields);
+
+ $item_fields = [];
+ if ( !empty($diff_fields) ) {
+ $describe = $this->send_get("$this->base_url/catalog/item/describe", $token, []);
+ foreach ($describe['fields'] as $field) {
+ array_push($item_fields, $field['name']);
+ }
+ }
+
+ /**
+ * Check one last time. If there are still unvalidated fields, they should be
+ * bibliographic tag fields used for filtering results. Throw an error if we find
+ * anything that doesn't look like a filter field.
+ */
+ $diff_fields = array_diff($diff_fields, $item_fields);
+
+ if ( !empty($diff_fields) ) {
+ foreach ($diff_fields as $field) {
+ if ( !preg_match("/^\d{3}(_[a-zA-Z0-9]{1})*$/", $field) ) {
+ throw new Exception ("Invalid field \"$field\" in includeFields");
}
- $i++;
}
}
- return $return;
+ return 1;
}
/**
@@ -688,212 +803,319 @@ public function change_item_library ($token = null, $item_key = null, $library =
}
/**
- * Get catalog search indexes
- *
- * @access public
- * @param string $token Session token returned by ILSWS
- * @return array $search_indexes Array of valid index names
+ * Retrieves bib information
+ *
+ * @param string $token Session token returned by ILSWS
+ * @param string $bib_key Bibliographic record key
+ * @param string $field_list Comma or comma and space delimited list of fields
+ * to be returned
+ * @return object Flat associative array containing bib information
*/
- public function get_catalog_indexes ($token = null)
+ public function get_bib ($token = null, $bib_key = null, $field_list = '')
{
- $search_indexes = [];
+ $bib = [];
+ $fields = preg_split("/[,{}]+/", $field_list, -1, PREG_SPLIT_NO_EMPTY);
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('bib_key', $bib_key, 'r:#^\d{1,8}$#');
- $describe = $this->send_get("$this->base_url/catalog/bib/describe", $token, []);
-
- foreach ($describe['searchIndexList'] as $index) {
- array_push($search_indexes, $index['name']);
+ // Validate the $field_list
+ if ( $this->config['symphony']['validate_catalog_fields'] ) {
+ $this->validate_bib_fields($token, $field_list);
+ } else {
+ $this->validate('field_list', $field_list, 'r:#^[A-Z0-9a-z_{},*]{2,256}$#');
}
- return $search_indexes;
- }
+ $response = $this->send_get("$this->base_url/catalog/bib/key/$bib_key?includeFields=" . $field_list, $token, []);
- /**
- * Validate bib field names using the API describe functions
- *
+ if ( !empty($response['fields']) ) {
+
+ // Flatten the structure to a simple hash
+ $temp = $this->flatten_bib($token, $response['fields']);
+
+ // Filter out empty or not requested fields
+
+ $bib['key'] = $response['key'];
+ foreach ($fields as $field) {
+ if ( !empty($temp[$field]) ) {
+ $bib[$field] = $temp[$field];
+ }
+ }
+ }
+
+ return $bib;
+ }
+
+ /**
+ * Retrieves item information
+ *
* @param string $token Session token returned by ILSWS
- * @param string $field_list Comma-delimited list of fields to be validated
- * @return object $response Object containing include list, array of
- * valid_fields, array of filter fields, array
- * of include fields, and index list.
+ * @param string $item_key Item key
+ * @param string $field_list Comma or comma and space delimited list of fields
+ * to be returned
+ * @return object Flat associative array containing item information
*/
- private function validate_bib_fields ($token = null, $field_list = '')
+ public function get_item ($token = null, $item_key = null, $field_list = '*')
{
- $response = [];
+ $item = [];
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('item_key', $item_key, 'r:#^(\d{6,8})(:\d{1,2}){0,2}$#');
- // Convert the input fields to an array
- $input_fields = preg_split("/[,{}]/", $field_list, -1, PREG_SPLIT_NO_EMPTY);
-
- // Get the fields to validate against
- $bib_fields = [];
- $describe = $this->send_get("$this->base_url/catalog/bib/describe", $token, []);
- foreach ($describe['fields'] as $field) {
- array_push($bib_fields, $field['name']);
+ // Validate the $field_list
+ if ( $this->config['symphony']['validate_catalog_fields'] ) {
+ $this->validate_fields($token, 'item', $field_list);
+ } else {
+ $this->validate('field_list', $field_list, 'r:#^[A-Za-z0-9_{},*]{2,256}$#');
}
- array_push($bib_fields, '*');
- array_push($bib_fields, 'key');
- /**
- * Check if there are unvalidated fields left after checking against
- * bib fields. If there are, check against call fields, next.
- */
- $diff_fields = array_diff($input_fields, $bib_fields);
+ $item = $this->send_get("$this->base_url/catalog/item/key/$item_key?includeFields=$field_list", $token, []);
- $call_fields = [];
- if ( !empty($diff_fields) ) {
- $describe = $this->send_get("$this->base_url/catalog/call/describe", $token, []);
- foreach ($describe['fields'] as $field) {
- array_push($call_fields, $field['name']);
- }
+ if ( !empty($item['fields']) ) {
+ $item = $this->flatten_item($token, $item);
}
- /**
- * Check again. if there are still unvalidated fields after checking against
- * the call fields, check against item fields.
- */
- $diff_fields = array_diff($diff_fields, $call_fields);
+ return $item;
+ }
- $item_fields = [];
- if ( !empty($diff_fields) ) {
- $describe = $this->send_get("$this->base_url/catalog/item/describe", $token, []);
- foreach ($describe['fields'] as $field) {
- array_push($item_fields, $field['name']);
- }
+ /**
+ * Get a call number
+ *
+ * @param string $token Session token returned by ILSWS
+ * @param string $call_key Call number key
+ * @return object Flat associative array containing the response from ILSWS
+ */
+
+ public function get_call_number ($token = null, $call_key = null, $field_list = '*')
+ {
+ $call = [];
+
+ $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('call_key', $call_key, 'r:#^\d{6,8}:\d{1,2}$#');
+
+ // Validate the $field_list
+ if ( $this->config['symphony']['validate_catalog_fields'] ) {
+ $this->validate_fields($token, 'call', $field_list);
+ } else {
+ $this->validate('field_list', $field_list, 'r:#^[A-Z0-9a-z_{},*]{2,256}$#');
}
- /**
- * Check one last time. If there are still unvalidated fields, they should be
- * bibliographic tag fields used for filtering results. Throw an error if we find
- * anything that doesn't look like a filter field.
- */
- $diff_fields = array_diff($diff_fields, $item_fields);
+ $call = $this->send_get("$this->base_url/catalog/call/key/$call_key?includeFields=$field_list", $token);
- if ( !empty($diff_fields) ) {
- foreach ($diff_fields as $field) {
- if ( !preg_match("/^\d{3}(_[a-zA-Z0-9]{1})*$/", $field) ) {
- throw new Exception ("Invalid field \"$field\" in includeFields");
- }
- }
+ if ( !empty($call['fields']) ) {
+ $call = $this->flatten_call($token, $call);
}
- return 1;
+ return $call;
}
/**
- * Get bib MARC data
+ * Describes the item record (used to determine valid indexes and fields)
*
- * @param string $token Session token returned by ILSWS
- * @param string $bib_key Bibliographic record key
- * @return array Flat associative array with MARC record
+ * @param string $token The session token returned by ILSWS
+ * @return object Associative array of response from ILSWS
*/
- public function get_bib_marc ($token = null, $bib_key = null)
+ public function describe_item ($token = null)
{
- $bib = [];
+ $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+
+ return $this->send_get("$this->base_url/catalog/item/describe", $token, []);
+ }
+
+ /**
+ * Describes the bib record (used to determine valid indexes and fields)
+ *
+ * @param string $token The session token returned by ILSWS
+ * @return object Associative array of response from ILSWS
+ */
+ public function describe_bib ($token = null)
+ {
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('bib_key', $bib_key, 'r:#^\d{1,8}$#');
+
+ return $this->send_get("$this->base_url/catalog/bib/describe", $token, []);
+ }
- $response = $this->send_get("$this->base_url/catalog/bib/key/$bib_key", $token, []);
+ /**
+ * Removes accents, punctuation, and non-ascii characters to
+ * create search string acceptable to ILSWS
+ *
+ * @param string $terms
+ * @return string $terms
+ */
- if ( !empty($response['fields']['bib']) ) {
- $bib['key'] = $response['key'];
- foreach ($response['fields']['bib'] as $marc_key => $marc_value) {
- if ( !is_array($marc_value) ) {
- $bib[$marc_key] = $marc_value;
- } else {
- foreach ($marc_value as $tag) {
- if ( !empty($tag['tag']) ) {
- foreach ($tag['subfields'] as $subfield) {
- if ( $subfield['code'] == '_' ) {
- $bib[$tag['tag']] = $subfield['data'];
- } else {
- $bib[$tag['tag'] . ' ' . $tag['inds'] . ' _' . $subfield['code']] = $subfield['data'];
- }
- }
+ public function prepare_search ($terms = null)
+ {
+ // Trim leading and trailing whitespace
+ $terms = trim($terms);
+
+ // Validate
+ $this->validate('terms', $terms, 's:256');
+
+ // Change utf8 letters with accents to ascii characters
+ setlocale(LC_ALL, "en_US.utf8");
+ $terms = iconv("utf-8", "ASCII//TRANSLIT", $terms);
+
+ // Remove boolean operators
+ $terms = preg_replace("/(\s+)(and|or|not)(\s+)/", ' ', $terms);
+
+ // Replace certain characters with a space
+ $terms = preg_replace("/[\\\:;,\/\|]/", ' ', $terms);
+
+ // Remove most punctuation and other unwanted characters
+ $terms = preg_replace("/[!?&+=><%#\'\"\{\}\(\)\[\]]/", '', $terms);
+
+ // Remove internal non-printing characters
+ $terms = preg_replace('/[^\x20-\x7E]/','', $terms);
+
+ // Replace multiple spaces with a single space
+ $terms = preg_replace('/\s+/', ' ', $terms);
+
+ return $terms;
+ }
+
+ /**
+ * Search the catalog for bib records
+ *
+ * @param string $token The session token returned by ILSWS
+ * @param string $index The index to search
+ * @param string $value The value to search for
+ * @param object $params Associative array of optional parameters
+ * @return object Associative array containing search results
+ */
+
+ public function search_bib ($token = null, $index = null, $value = null, $params = null)
+ {
+ $fields = preg_split("/[,{}]+/", $params['includeFields'], -1, PREG_SPLIT_NO_EMPTY);
+
+ $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
+ $this->validate('value', $value, 's:40');
+
+ if ( $this->config['symphony']['validate_catalog_fields'] ) {
+
+ // Validate fields and get valid search indexes
+ $this->validate_bib_fields($token, $params['includeFields']);
+
+ // Validate the search index
+ $index_list = $this->get_catalog_indexes($token);
+ $this->validate('index', $index, 'v:' . implode('|', $index_list));
+
+ } else {
+ $this->validate('includeFields', $params['includeFields'], 'r:#^[A-Z0-9a-z_{},]{2,256}$#');
+ }
+
+ /**
+ * Valid incoming params are:
+ * ct = number of results to return,
+ * rw = row to start on (so you can page through results),
+ * j = boolean AND or OR to use with multiple search terms, and
+ * includeFields = fields to return in result.
+ *
+ * Any incoming q will be replaced by the values $index and $value.
+ */
+
+ $params = [
+ 'q' => "$index:$value",
+ 'ct' => $params['ct'] ?? '1000',
+ 'rw' => $params['rw'] ?? '1',
+ 'j' => $params['j'] ?? 'AND',
+ 'includeFields' => $params['includeFields'],
+ ];
+
+ $response = $this->send_get("$this->base_url/catalog/bib/search", $token, $params);
+
+ $records = [];
+ if ( !empty($response['totalResults']) && $response['totalResults'] > 0 ) {
+
+ for ($i = 0; $i < count($response['result']); $i++) {
+
+ if ( !is_null($response['result'][$i]) ) {
+
+ $bib = $this->flatten_bib($token, $response['result'][$i]['fields']);
+ $bib['key'] = $response['result'][$i]['key'];
+
+ $filtered_bib = [];
+ foreach ($fields as $field) {
+ if ( !empty($bib[$field]) ) {
+ $filtered_bib[$field] = $bib[$field];
}
}
+ array_push($records, $filtered_bib);
}
}
}
- return $bib;
+ return $records;
}
/**
- * Get bibliographic circulation statistics
+ * Pulls list of items checked out to a patron
*
- * @param string $token Session token returned by ILSWS
- * @param string $bib_key Bibliographic record key
- * @return object Flat associative array with circulation numbers
+ * @access public
+ * @param string $token Session token returned by ILSWS
+ * @param integer $patron_key Patron key of patron whose records we need to see
+ * @param string $include_fields Optional
+ * @return array $return Associative array of item keys and libraries
*/
- public function get_bib_circ_info ($token = null, $bib_key = null)
+ public function get_patron_checkouts ($token = null, $patron_key = null, $include_fields = null)
{
- $stats = [];
-
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('bib_key', $bib_key, 'r:#^\d{1,8}$#');
-
- $response = $this->send_get("$this->base_url/circulation/bibCircInfo/key/$bib_key", $token, []);
+ $this->validate('patron_key', $patron_key, 'r:#^d{1,6}$#');
- if ( !empty($response['fields']) ) {
- foreach ($response['fields'] as $field => $value) {
- $stats[$field] = $value;
+ if (!$include_fields) {
+ $include_fields = 'item,library';
+ }
+
+ $response = $this->send_get("$this->base_url/user/patron/key/$patron_key?includeFields=circRecordList{*}", $token, []);
+ $fields = preg_split('/,/', $include_fields);
+
+ $return = [];
+ $i = 0;
+ if (count($response) > 0) {
+ foreach ($response['fields']['circRecordList'] as $item) {
+ foreach ($fields as $field) {
+ $data = $item['fields'][$field];
+ if (is_array($data)) {
+ $return[$i][$field] = $data['key'];
+ } else {
+ $return[$i][$field] = $data;
+ }
+ }
+ $i++;
}
}
- return $stats;
+ return $return;
}
/**
- * Retrieves bib information
+ * Get bibliographic circulation statistics
*
* @param string $token Session token returned by ILSWS
* @param string $bib_key Bibliographic record key
- * @param string $field_list Comma or comma and space delimited list of fields
- * to be returned
- * @return object Flat associative array containing bib information
+ * @return object Flat associative array with circulation numbers
*/
- public function get_bib ($token = null, $bib_key = null, $field_list = '')
+ public function get_bib_circ_info ($token = null, $bib_key = null)
{
- $bib = [];
- $fields = preg_split("/[,{}]+/", $field_list, -1, PREG_SPLIT_NO_EMPTY);
+ $stats = [];
$this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
$this->validate('bib_key', $bib_key, 'r:#^\d{1,8}$#');
-
- // Validate the $field_list
- if ( $this->config['symphony']['validate_catalog_fields'] ) {
- $this->validate_bib_fields($token, $field_list);
- } else {
- $this->validate('field_list', $field_list, 'r:#^[A-Z0-9a-z_{},*]{2,256}$#');
- }
-
- $response = $this->send_get("$this->base_url/catalog/bib/key/$bib_key?includeFields=" . $field_list, $token, []);
+
+ $response = $this->send_get("$this->base_url/circulation/bibCircInfo/key/$bib_key", $token, []);
if ( !empty($response['fields']) ) {
-
- // Flatten the structure to a simple hash
- $temp = $this->flatten_bib($token, $response['fields']);
-
- // Filter out empty or not requested fields
-
- $bib['key'] = $response['key'];
- foreach ($fields as $field) {
- if ( !empty($temp[$field]) ) {
- $bib[$field] = $temp[$field];
- }
+ foreach ($response['fields'] as $field => $value) {
+ $stats[$field] = $value;
}
}
- return $bib;
+ return $stats;
}
/**
@@ -926,39 +1148,6 @@ public function get_item_circ_info ($token = null, $item_key = null)
return $stats;
}
- /**
- * Retrieves item information
- *
- * @param string $token Session token returned by ILSWS
- * @param string $item_key Item key
- * @param string $field_list Comma or comma and space delimited list of fields
- * to be returned
- * @return object Flat associative array containing item information
- */
-
- public function get_item ($token = null, $item_key = null, $field_list = '*')
- {
- $item = [];
-
- $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('item_key', $item_key, 'r:#^(\d{6,8})(:\d{1,2}){0,2}$#');
-
- // Validate the $field_list
- if ( $this->config['symphony']['validate_catalog_fields'] ) {
- $this->validate_fields($token, 'item', $field_list);
- } else {
- $this->validate('field_list', $field_list, 'r:#^[A-Za-z0-9_{},*]{2,256}$#');
- }
-
- $item = $this->send_get("$this->base_url/catalog/item/key/$item_key?includeFields=$field_list", $token, []);
-
- if ( !empty($item['fields']) ) {
- $item = $this->flatten_item($token, $item);
- }
-
- return $item;
- }
-
/**
* Flatten hold record
*
@@ -1009,54 +1198,6 @@ public function get_hold ($token = null, $hold_key = null)
return $hold;
}
- /**
- * Get a call number
- *
- * @param string $token Session token returned by ILSWS
- * @param string $call_key Call number key
- * @return object Flat associative array containing the response from ILSWS
- */
-
- public function get_call_number ($token = null, $call_key = null, $field_list = '*')
- {
- $call = [];
-
- $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('call_key', $call_key, 'r:#^\d{6,8}:\d{1,2}$#');
-
- // Validate the $field_list
- if ( $this->config['symphony']['validate_catalog_fields'] ) {
- $this->validate_fields($token, 'call', $field_list);
- } else {
- $this->validate('field_list', $field_list, 'r:#^[A-Z0-9a-z_{},*]{2,256}$#');
- }
-
- $call = $this->send_get("$this->base_url/catalog/call/key/$call_key?includeFields=$field_list", $token);
-
- if ( !empty($call['fields']) ) {
- $call = $this->flatten_call($token, $call);
- }
-
- return $call;
- }
-
- /**
- * Get policy returns a policy record
- *
- * @param string $token Session token returned by ILSWS
- * @param string $policy_name Policy name for policy
- * @param string $policy_key Policy key for policy
- * @return object Associative array containing the response from ILSWS
- */
-
- public function get_policy ($token = null, $policy_name = null, $policy_key = null)
- {
- $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('policy_name', $policy_name, 'r:#^[A-Za-z0-9]{1,20}$#');
- $this->validate('policy_key', $policy_key, 'r:#^[A-Za-z\- 0-9]{1,10}$#');
-
- return $this->send_get("$this->base_url/policy/$policy_name/key/$policy_key", $token, []);
- }
/**
* Removes URLs from the trailing end of a string
@@ -1119,146 +1260,6 @@ public function get_library_paging_list ($token = null, $library_key = null)
return $list;
}
- /**
- * Describes the item record (used to determine valid indexes and fields)
- *
- * @param string $token The session token returned by ILSWS
- * @return object Associative array of response from ILSWS
- */
-
- public function describe_item ($token = null)
- {
- $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
-
- return $this->send_get("$this->base_url/catalog/item/describe", $token, []);
- }
-
- /**
- * Describes the bib record (used to determine valid indexes and fields)
- *
- * @param string $token The session token returned by ILSWS
- * @return object Associative array of response from ILSWS
- */
-
- public function describe_bib ($token = null)
- {
- $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
-
- return $this->send_get("$this->base_url/catalog/bib/describe", $token, []);
- }
-
- /**
- * Removes accents, punctuation, and non-ascii characters to
- * create search string acceptable to ILSWS
- *
- * @param string $terms
- * @return string $terms
- */
-
- public function prepare_search ($terms = null)
- {
- // Trim leading and trailing whitespace
- $terms = trim($terms);
-
- // Validate
- $this->validate('terms', $terms, 's:256');
-
- // Change utf8 letters with accents to ascii characters
- setlocale(LC_ALL, "en_US.utf8");
- $terms = iconv("utf-8", "ASCII//TRANSLIT", $terms);
-
- // Remove boolean operators
- $terms = preg_replace("/(\s+)(and|or|not)(\s+)/", ' ', $terms);
-
- // Replace certain characters with a space
- $terms = preg_replace("/[\\\:;,\/\|]/", ' ', $terms);
-
- // Remove most punctuation and other unwanted characters
- $terms = preg_replace("/[!?&+=><%#\'\"\{\}\(\)\[\]]/", '', $terms);
-
- // Remove internal non-printing characters
- $terms = preg_replace('/[^\x20-\x7E]/','', $terms);
-
- // Replace multiple spaces with a single space
- $terms = preg_replace('/\s+/', ' ', $terms);
-
- return $terms;
- }
-
- /**
- * Search the catalog for bib records
- *
- * @param string $token The session token returned by ILSWS
- * @param string $index The index to search
- * @param string $value The value to search for
- * @param object $params Associative array of optional parameters
- * @return object Associative array containing search results
- */
-
- public function search_bib ($token = null, $index = null, $value = null, $params = null)
- {
- $fields = preg_split("/[,{}]+/", $params['includeFields'], -1, PREG_SPLIT_NO_EMPTY);
-
- $this->validate('token', $token, 'r:#^[a-z0-9\-]{36}$#');
- $this->validate('value', $value, 's:40');
-
- if ( $this->config['symphony']['validate_catalog_fields'] ) {
-
- // Validate fields and get valid search indexes
- $this->validate_bib_fields($token, $params['includeFields']);
-
- // Validate the search index
- $index_list = $this->get_catalog_indexes($token);
- $this->validate('index', $index, 'v:' . implode('|', $index_list));
-
- } else {
- $this->validate('includeFields', $params['includeFields'], 'r:#^[A-Z0-9a-z_{},]{2,256}$#');
- }
-
- /**
- * Valid incoming params are:
- * ct = number of results to return,
- * rw = row to start on (so you can page through results),
- * j = boolean AND or OR to use with multiple search terms, and
- * includeFields = fields to return in result.
- *
- * Any incoming q will be replaced by the values $index and $value.
- */
-
- $params = [
- 'q' => "$index:$value",
- 'ct' => $params['ct'] ?? '1000',
- 'rw' => $params['rw'] ?? '1',
- 'j' => $params['j'] ?? 'AND',
- 'includeFields' => $params['includeFields'],
- ];
-
- $response = $this->send_get("$this->base_url/catalog/bib/search", $token, $params);
-
- $records = [];
- if ( !empty($response['totalResults']) && $response['totalResults'] > 0 ) {
-
- for ($i = 0; $i < count($response['result']); $i++) {
-
- if ( !is_null($response['result'][$i]) ) {
-
- $bib = $this->flatten_bib($token, $response['result'][$i]['fields']);
- $bib['key'] = $response['result'][$i]['key'];
-
- $filtered_bib = [];
- foreach ($fields as $field) {
- if ( !empty($bib[$field]) ) {
- $filtered_bib[$field] = $bib[$field];
- }
- }
- array_push($records, $filtered_bib);
- }
- }
- }
-
- return $records;
- }
-
/**
* Deletes a patron
*
From cd3359a207a07e6bc4486456db8cd0686c1de52c Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Fri, 1 Mar 2024 09:23:50 -0800
Subject: [PATCH 6/8] Improved validation function
---
src/Libilsws.php | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/Libilsws.php b/src/Libilsws.php
index 1eeed0b..2809aeb 100644
--- a/src/Libilsws.php
+++ b/src/Libilsws.php
@@ -174,11 +174,12 @@ private function validate_fields ($token = null, $type = null, $field_list = '')
private function validate ($param, $value, $rule)
{
- if ( !$this->dh->validate($value, $rule) ) {
+ $result = $this->dh->validate($value, $rule);
+ if ( $result === 0 ) {
throw new Exception ("Invalid $param: \"$value\" (rule: '$rule')");
}
- return 1;
+ return $result;
}
/**
From 8309ed0fdb57a789ec58cb03a19429b1b745d031 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Fri, 1 Mar 2024 10:43:05 -0800
Subject: [PATCH 7/8] Remove unused debug variable from DataHandler.php
---
src/DataHandler.php | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/DataHandler.php b/src/DataHandler.php
index 282e1a2..735e6cb 100644
--- a/src/DataHandler.php
+++ b/src/DataHandler.php
@@ -16,10 +16,6 @@
class DataHandler
{
-
- // Set to 1 for dubugging messages
- private $debug = 0;
-
/**
* Validates various types of incoming field data
* Sample fields hash with validation rules:
@@ -67,7 +63,7 @@ public function validate ($value, $validation_rule) {
switch ($type) {
case "b":
// Value must be undefined
- if ( ! defined($value) ) {
+ if ( !defined($value) ) {
$retval = 1;
}
break;
@@ -92,7 +88,7 @@ public function validate ($value, $validation_rule) {
break;
case "j":
// Must be valid JSON
- if ( ! empty($value) ) {
+ if ( !empty($value) ) {
json_decode($value);
if ( json_last_error() == JSON_ERROR_NONE ) {
$retval = 1;
@@ -129,7 +125,7 @@ public function validate ($value, $validation_rule) {
break;
case "s":
// Check string for length
- if ( ! defined($value) || strlen($value) <= $param ) {
+ if ( !defined($value) || strlen($value) <= $param ) {
$retval = 1;
}
break;
From 4a6c666596b804c25358d12f89bff3499ae05f69 Mon Sep 17 00:00:00 2001
From: John Houser <90853393+john-c-houser@users.noreply.github.com>
Date: Fri, 1 Mar 2024 12:30:50 -0800
Subject: [PATCH 8/8] Fixed integer validation
---
src/DataHandler.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/DataHandler.php b/src/DataHandler.php
index 735e6cb..cb28222 100644
--- a/src/DataHandler.php
+++ b/src/DataHandler.php
@@ -81,9 +81,11 @@ public function validate ($value, $validation_rule) {
break;
case "i":
// Must be an integer of length specified
- list($min_range, $max_range) = preg_split('/,/', $param);
- if ( filter_var($value, FILTER_VALIDATE_INT, ['options' => ['min_range' => $min_range, 'max_range' => $max_range]]) ) {
- $retval = 1;
+ if ( preg_match('/^-?\d+$/', $value) ) {
+ list($min_range, $max_range) = preg_split('/,/', $param);
+ if ( filter_var($value, FILTER_VALIDATE_INT, ['options' => ['min_range' => $min_range, 'max_range' => $max_range]]) ) {
+ $retval = 1;
+ }
}
break;
case "j":