forked from Islandora/islandora_checksum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathislandora_checksum.module
339 lines (322 loc) · 11.3 KB
/
islandora_checksum.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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
<?php
/**
* @file
* The main checksum module file. Contains most of the hook implementations.
*
* @todo Add uninstall hook to delete our the variables we set.
*/
/**
* Implements hook_menu().
*/
function islandora_checksum_menu() {
$items = array();
$items['admin/islandora/tools/checksum'] = array(
'title' => 'Checksum',
'description' => 'Configure the Islandora Checksum creator.',
'page callback' => 'drupal_get_form',
'access arguments' => array('administer site configuration'),
'page arguments' => array('islandora_checksum_admin_form'),
'file' => 'includes/admin.form.inc',
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Implements hook_islandora_datastream_alter().
*/
function islandora_checksum_islandora_datastream_alter(AbstractObject $object, AbstractDatastream $datastream, &$context) {
if ($context['action'] == 'ingest' && variable_get('islandora_checksum_enable_checksum', FALSE) && islandora_checksum_dsid_is_in_filter($datastream->id)) {
$datastream->checksumType = variable_get('islandora_checksum_checksum_type', 'DISABLED');
}
}
/**
* Implements hook_islandora_derivative_alter().
*/
function islandora_checksum_islandora_derivative_alter(&$derivatives, AbstractObject $object = NULL, $ds_modified_params = array()) {
if (!empty($ds_modified_params) && variable_get('islandora_checksum_deriv_regeneration_bypass', FALSE)) {
// When only the checksumType is modified, we don't want to trigger
// derivative regeneration.
$diff = array_diff_key($ds_modified_params, array(
'checksumType' => NULL,
'dateLastModified' => NULL,
'dsid' => NULL,
));
if (empty($diff)) {
$derivatives = array();
}
}
}
/**
* Query the resource index to get a list of collections.
*
* @return array
* List of collection PIDs.
*/
function islandora_checksum_get_collections() {
module_load_include('inc', 'islandora_basic_collection', 'includes/utilities');
$root = islandora_object_load(variable_get('islandora_repository_pid', 'islandora:root'));
return islandora_basic_collection_get_other_collections_as_form_options($root);
}
/**
* Query the RI index for collection member details.
*
* @param string $pid
* The PID of Islandora collection.
* @param bool $count
* Whether this is a countQuery or not.
* @param int $limit
* The number of items to return.
* @param array $slice_params
* An optional associative array of parameters to pass in to properly grab
* the slice, including:
* - 'offset_date': an ISO8601 date to filter items before
* - 'offset_pid': a PID to filter items before if dates match.
*
* @return array
* Associative array of RI results, containg the 'object' as the object PID,
* and the 'date' as the object's createdDate.
*/
function islandora_checksum_get_collection_member_details($pid, $count = FALSE, $limit = 10, $slice_params = array()) {
// List of objects to create checksums for.
$members = array();
// Query the rindex to get all the objects that have a 'isMemberOfCollection'
// relationship with the specified collection and add all their PIDs to the
// list.
$tuque = islandora_get_tuque_connection();
$islandora_rels_ext = ISLANDORA_RELS_EXT_URI;
$ri_query = <<<EOF
PREFIX xs: <xml-schema:>
SELECT DISTINCT ?object ?date
FROM <#ri>
WHERE {
{
?object <fedora-rels-ext:isMemberOfCollection> <info:fedora/$pid> .
} UNION {
?object <{$islandora_rels_ext}isPageOf> ?book .
?book <fedora-rels-ext:isMemberOfCollection> <info:fedora/$pid> .
} UNION {
?object <fedora-rels-ext:isConstituentOf> ?compound .
?compound <fedora-rels-ext:isMemberOfCollection> <info:fedora/$pid> .
} UNION {
?object <fedora-rels-ext:isMemberOf> ?issue .
?issue <fedora-rels-ext:isMemberOf> ?newspaper .
?newspaper <fedora-rels-ext:isMemberOfCollection> <info:fedora/$pid> .
}
?object <fedora-model:createdDate> ?date .
EOF;
if ($slice_params) {
$ri_query .= <<<EOF
FILTER(?date > '{$slice_params['offset_date']}'^^xs:dateTime || (?date = '{$slice_params['offset_date']}'^^xs:dateTime && xs:string(?object) > xs:string('info:fedora/{$slice_params['offset_pid']}')))
}
ORDER BY ASC(?date) ASC(?object)
EOF;
}
else {
$ri_query .= <<<EOF
}
EOF;
}
if ($count) {
return $tuque->repository->ri->countQuery($ri_query, 'sparql');
}
return $tuque->repository->ri->sparqlQuery($ri_query, $limit);
}
/**
* Query the RI index to get PIDs of all child objects in a collection.
*
* @param string $pid
* The PID of Islandora collection.
* @param int $limit
* The number of items to return.
* @param array $slice_params
* An optional associative array of parameters to pass in to properly grab
* the slice, including:
* - 'offset_date': an ISO8601 date to filter items before
* - 'offset_pid': a PID to filter items before if dates match.
*
* @return array
* List of member object PIDs.
*/
function islandora_checksum_get_collection_members($pid, $limit = 10, $slice_params = array()) {
module_load_include('inc', 'islandora', 'includes/utilities');
$message = islandora_deprecated('7.x-1.8', t('Code should be updated to use islandora_checksum_get_collection_member_details(), which provides both the PID and createdDate of objects so that accurate slicing of member sets can be performed.'));
trigger_error(filter_xss($message), E_USER_DEPRECATED);
$results = islandora_checksum_get_collection_member_details($pid, FALSE, $limit, $slice_params);
$members = array();
foreach ($results as $result) {
$members[] = $member['object']['value'];
}
return $members;
}
/**
* Custom button submit handler.
*/
function islandora_checksum_apply_retro($form, &$form_state) {
batch_set(islandora_checksum_get_collection_checksum_update_batch($form_state['values']['collection']));
}
/**
* Gets the batch definition for enabling or re-applying checksums.
*
* @param string $collection_pid
* The PID of the collection to apply checksums to.
* @param int $limit
* The number of items to do per-batch.
* @param array $dsids
* The DSIDs to apply checksums to. Leave empty to use the default
* configuration.
*
* @return array
* The batch definition.
*/
function islandora_checksum_get_collection_checksum_update_batch($collection_pid, $limit = 10, $dsids = array()) {
if (empty($dsids)) {
$dsids = islandora_checksum_unpack_dsid_filter();
}
return array(
'operations' => array(
array(
'islandora_checksum_enable_object_checksums',
array(
$collection_pid,
$limit,
$dsids,
),
),
),
'title' => 'Enabling checksums',
'finished' => 'islandora_checksum_batch_finished',
'init_message' => t('Getting objects to checksum ...'),
'progress_message' => t('Time elapsed: @elapsed <br/>Estimated time remaining: @estimate.'),
'error_message' => t('An error occurred and not all checksums were set.'),
);
}
/**
* Sets up the batch.
*
* @param string $collection_pid
* The PID of the collection to apply checksums to.
*
* @return array
* The batch.
*/
function islandora_checksum_enable_retro_checksums($collection_pid) {
module_load_include('inc', 'islandora', 'includes/utilities');
$message = islandora_deprecated('7.x-1.8', t('As this function relies on getting every member of a collection to build the batch, it can time out or run out of memory when attempting to do so on exceptionally large collections. Code should be changed to use islandora_checksum_get_collection_checksum_update_batch(), which instead does a single batch operation that iterates over object sets.'));
trigger_error(filter_xss($message), E_USER_DEPRECATED);
$pids = islandora_checksum_get_collection_members($collection_pid);
$operations = array();
$num_objects = count($pids);
foreach ($pids as $pid) {
$operations[] = array('islandora_checksum_enable_object_checksums',
array($pid, $num_objects),
);
}
$batch = array(
'operations' => $operations,
'title' => 'Enabling checksums',
'finished' => 'islandora_checksum_batch_finished',
);
return $batch;
}
/**
* Batch process to enable checksums for a collection's children.
*
* @param string $collection
* The PID of the collection.
* @param int $limit
* The number of items to do per-iteration.
* @param array $dsids
* The datastream DSIDs to target.
* @param array $context
* The batch context.
*/
function islandora_checksum_enable_object_checksums($collection, $limit, $dsids, &$context) {
$sandbox = &$context['sandbox'];
module_load_include('inc', 'islandora_checksum', 'includes/checksum');
if (empty($sandbox)) {
$sandbox['total'] = islandora_checksum_get_collection_member_details($collection, TRUE);
if ($sandbox['total'] == 0) {
$context['message'] = t('No objects to apply checksums to.');
$context['finished'] = 1;
return;
}
$sandbox['current'] = 0;
$sandbox['offset_params'] = NULL;
$sandbox['checksum_type'] = variable_get('islandora_checksum_checksum_type', 'DISABLED');
}
$slice = islandora_checksum_get_collection_member_details($collection, FALSE, $limit, $sandbox['offset_params']);
foreach ($slice as $member) {
islandora_checksum_set_checksums($member['object']['value'], $dsids, $sandbox['checksum_type']);
$sandbox['current']++;
$sandbox['offset_params'] = array(
'offset_pid' => $member['object']['value'],
'offset_date' => $member['date']['value'],
);
$context['results'][] = $member['object']['value'];
}
$context['message'] = t('Set checksums for @current/@total objects.', array(
'@current' => $sandbox['current'],
'@total' => $sandbox['total'],
));
$context['finished'] = $sandbox['current'] / $sandbox['total'];
}
/**
* Batch 'finished' callback.
*/
function islandora_checksum_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('Checksums enabled for @count objects.', array('@count' => count($results))));
}
else {
// An error occurred.
$error_operation = reset($operations);
drupal_set_message(t('An error occurred while processing @operation with arguments : @args',
array(
'@operation' => $error_operation[0],
'@args' => print_r($error_operation[0], TRUE))
)
);
}
}
/**
* Get array of DSIDs to apply checksums to.
*
* @return array
* Array of DSIDs, if not empty then only these DSIDs will get checksums.
*/
function islandora_checksum_unpack_dsid_filter() {
$datastreams_to_check = &drupal_static(__FUNCTION__);
if (is_null($datastreams_to_check)) {
if (strlen(variable_get('islandora_checksum_dsids_to_check', ''))) {
$datastreams_to_check = explode(',',
variable_get('islandora_checksum_dsids_to_check', ''));
}
else {
$datastreams_to_check = array();
}
// Make sure there are no spaces around the DSIDs, so we can get a
// match in in_array().
foreach ($datastreams_to_check as &$dsid) {
$dsid = trim($dsid);
}
}
return $datastreams_to_check;
}
/**
* Checks if a DSID is in the DSID filter.
*
* @param string $dsid
* The DSID to check.
*
* @return bool
* Whether or not the DSID was in the filter.
*/
function islandora_checksum_dsid_is_in_filter($dsid) {
$filter = islandora_checksum_unpack_dsid_filter();
if (count($filter) === 0) {
return TRUE;
}
else {
return in_array($dsid, $filter);
}
}