-
Notifications
You must be signed in to change notification settings - Fork 10
/
alma.module
250 lines (224 loc) · 6.73 KB
/
alma.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
<?php
/**
* @file alma.module
* Drupal module implementing Axiell ABs Alma API.
*/
/**
* Implementation of hook_flush_caches().
*/
function alma_flush_caches() {
return array('cache_alma_requests');
}
/**
* Implementation of hook_requirements().
*/
function alma_requirements($phase) {
$requirements = array();
// Ensure translations don't break at install time.
$t = get_t();
if (!function_exists('simplexml_load_string')) {
$requirements['simplexml'] = array(
'title' => 'SimpleXML',
'description' => $t('The Alma module requires SimpleXML to function. Please install and/or enable SimpleXML in your PHP configuration.'),
'severity' => REQUIREMENT_ERROR,
);
}
return $requirements;
}
/**
* Implementation of hook_trampoline_variables().
*/
function alma_trampoline_variables() {
$vars = array(
'alma_base_url',
);
foreach (_alma_cached_methods() as $name => $title) {
$vars[] = 'alma_' . $name . '_expire';
}
return $vars;
}
/**
* Implementation of hook_ctools_plugin_directory().
*/
function alma_ctools_plugin_directory($module, $plugin) {
if ($module == 'ding_provider') {
return "plugins/$plugin";
}
}
/**
* Return a fully instantiated AlmaClient instance.
*/
function alma_client() {
// This is basically a singleton. We also wait until right before
// instantiating to include our required classes. That seems like a
// decent performance tradeoff instead of loading everything on every
// page load.
static $client;
if (!isset($client)) {
$path = drupal_get_path('module', 'alma');
// How the hell it can be possible that we include this twice, I
// don't know, but I've seen it happen on the user page.
require_once($path . '/lib/AlmaClient/AlmaClient.class.php');
try {
$client = new AlmaClient(variable_get('alma_base_url', ''));
}
catch (Exception $e) {
watchdog('alma', 'Error instantiating AlmaClient: “@message”', array('@method' => $method, '@message' => $e->getMessage(), WATCHDOG_ERROR));
return NULL;
}
}
return $client;
}
/**
* Returns a list of cache candidate methods.
*/
function _alma_cached_methods() {
static $methods;
if (!$methods) {
$methods = array(
'get_reservation_branches' => t('Reservation branch list'),
'catalogue_record_detail' => t('Catalogue record details'),
'get_availability' => t('Availability data'),
);
}
return $methods;
}
/**
* Calls the Alma backend, possibly caching the result.
*
* @param $method
* The desired method.
* @param ...
* Arguments to the method.
*
* @return mixed
* NULL on error, or the result of the method call.
*/
function alma_client_invoke($method) {
static $cached_methods = array(
'get_reservation_branches' => 28800,
'catalogue_record_detail' => 28800,
'get_availability' => 28800,
);
$args = func_get_args();
array_shift($args); // Lose the method.
$expire = variable_get('alma_' . $method . '_expire', 0);
if ($expire) {
// Return data from cache if available.
$cid = 'alma:' . $method . ":" . md5(serialize($args));
$cache = cache_get($cid, 'cache_alma_requests');
if ($cache && !empty($cache->data)) {
return $cache->data;
}
}
$client = alma_client();
if (!$client) {
// Not much we can do.
return;
}
try {
$result = call_user_func_array(array($client, $method), $args);
}
catch (Exception $e) {
watchdog('alma', '@method error: “@message”', array('@method' => $method, '@message' => $e->getMessage(), WATCHDOG_ERROR));
return NULL;
}
if (isset($cid) && $result) {
cache_set($cid, $result, 'cache_alma_requests', $_SERVER['REQUEST_TIME'] + $expire);
}
return $result;
}
/**
* Clear the cache of a Alma method call.
*/
function alma_client_clear_cache($method) {
$cid = 'alma:' . $method . ":" . md5(serialize($args));
$cache = cache_clear_all($cid, 'cache_alma_requests');
}
/**
* Get the complete organisation info from Alma.
*
* Includes branches, departments, locations, sublocations and
* collections.
*
* @param boolean $reset
* Optional. If TRUE reset the cached data and reload.
* @return array
* Array of the different organisational unit, each an array of their
* member units.
*/
function alma_get_organisation($reset=FALSE) {
// Return data from cache if available.
$cache = ($reset) ? FALSE : cache_get('alma_get_organisation', 'cache_alma_requests');
if ($cache && !empty($cache->data)) {
$organisation = $cache->data;
}
else {
$organisation = array(
'branch' => alma_client_invoke('get_branches'),
'department' => alma_client_invoke('get_departments'),
'location' => alma_client_invoke('get_locations'),
'sublocation' => alma_client_invoke('get_sublocations'),
'collection' => alma_client_invoke('get_collections'),
);
// Cache output for 24 hours if we got all the data correctly.
if ($organisation['branch'] && $organisation['department'] && $organisation['location'] && $organisation['sublocation'] && $organisation['collection']) {
cache_set('alma_get_organisation', $organisation, 'cache_alma_requests', $_SERVER['REQUEST_TIME'] + 86400);
}
}
return $organisation;
}
/**
* Calculate the time to wait for a reservation.
*
* @param array $records
* The records array from a alma_client_catalogue_record_detail request.
* @return array
* Wait time, keyed by Alma ID.
*/
function alma_calculate_wait_time($records) {
$wait = array();
foreach ($records as $record) {
if ($record['available_count'] > 0) {
$wait[$record['alma_id']] = t('A couple of days');
}
else {
$total = 0;
foreach ($record['holdings'] as $holding) {
$total += $holding['total_count'];
}
if ($total > 0 && $record['reservation_count'] > 0) {
$days = $total / $record['reservation_count'] * 30;
if ($days < 9) {
$wait[$record['alma_id']] = t('About a week');
}
elseif ($days < 16) {
$wait[$record['alma_id']] = t('About two weeks');
}
elseif ($days < 35) {
$wait[$record['alma_id']] = t('About a month');
}
elseif ($days < 65) {
$wait[$record['alma_id']] = t('About two months');
}
else {
$wait[$record['alma_id']] = t('More than two months');
}
}
else {
$wait[$record['alma_id']] = t('Unknown');
}
}
}
return $wait;
}
/**
* Formats a date/time string as a ISO 8601 date without hours, minutes and seconds as required by Alma.
*
* @param string $datetime
* @return string Date in ISO 8601 YYYY-MM-DD format
*/
function alma_format_date($datetime) {
$timestamp = (!is_int($datetime)) ? strtotime($datetime) : $datetime;
return date('Y-m-d', $timestamp);
}