Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

embargo roles whitelist #232

Merged
merged 11 commits into from
May 24, 2016
4 changes: 3 additions & 1 deletion modules/islandora_scholar_embargo/includes/admin.form.inc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ function islandora_embargo_admin(array $form, array &$form_state) {
$options = islandora_get_content_models();
$selected = variable_get('islandora_embargo_content_models', array('ir:citationCModel', 'ir:thesisCModel'));
foreach ($selected as $cmodel) {
$options = array($cmodel => $options[$cmodel]) + $options;
if (isset($options[$cmodel])) {
$options = array($cmodel => $options[$cmodel]) + $options;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm... not sure I understand what's going on here. If there's an entry in $options, we reset its value to itself?

Are we looking for something more like:

$options = array_intersect_key($options, drupal_map_assoc($selected));

instead of this foreach over $selected?

... Actually... This was some craziness to establish the "desired" ordering or something, was it?

Copy link
Author

@qadan qadan Apr 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just because it's possible for those options not to be returned in islandora_get_content_models() due to XACML or other what-have-ye's, so $options[$cmodel] may not exist. But yeah, there's probably a more PHP-weird-array-business way to do it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it wasn't so much the isset(), but the whole: "options = one of it's items + the rest of it"... Which would only have the affect of (re)ordering the array...?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the intention was to place the current config at the top? Because ... UI design? I dunno?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shrug. Is fine.

}
foreach ($options as $key => $value) {
$rows[$key] = array(
Expand Down
73 changes: 73 additions & 0 deletions modules/islandora_scholar_embargo/includes/batch.inc
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,76 @@ function islandora_scholar_embargo_lift_batch_finished($success, $results, $oper
drupal_set_message(format_plural($results['skip_count'], '@count object skipped as the content model is not configured to allow embargoes.', '@count objects skipped as their content models are not configured to allow embargoes.'));
}
}

/**
* Batch definition for re-applying embargoes to embargoed objects.
*
* @return array
* The batch definition.
*/
function islandora_scholar_embargo_reapply_embargoes_batch() {
return array(
'title' => t('Re-Apply Embargos to Embargoed Objects'),
'error_message' => t('An error has occurred and the embargoes may not have all been re-applied.'),
'init_message' => t('Preparing to re-apply embargoes to embargoed objects.'),
'progress_message' => t('Time elapsed: @elapsed <br/>Estimated time remaining: @estimate.'),
'file' => drupal_get_path('module', 'islandora_scholar_embargo') . '/includes/batch.inc',
'operations' => array(
array('islandora_scholar_embargo_reapply_embargoes_batch_operation', array()),
),
);
}

/**
* Batch operation for re-applying embargoes to embargoed objects.
*
* @param array $context
* The batch context.
*/
function islandora_scholar_embargo_reapply_embargoes_batch_operation(&$context) {
module_load_include('inc', 'islandora_scholar_embargo', 'includes/embargo');
$sandbox =& $context['sandbox'];
if (empty($sandbox)) {
$sandbox['completed'] = 0;
$sandbox['slice'] = array();
}

// It's possible for this number to change during the batch (e.g., if an
// embargo expires or a datastream is modified), so re-grabbing is safest to
// prevent items from being skipped.
$sandbox['total'] = islandora_scholar_embargo_get_all_embargoed(TRUE);
if (!$sandbox['total']) {
$context['message'] = t('No items to embargo found, or embargoed items set was reduced to zero at some point during the batch.');
return;
}
else {
// Iterate through a set.
$set = islandora_scholar_embargo_get_embargoed_items_subset($sandbox['slice']);
if (!empty($set)) {
foreach ($set as $embargoed_item) {
$id_parts = explode('/', $embargoed_item['obj']['value']);
$pid = array_shift($id_parts);
$dsid = array_shift($id_parts);
$dsids = is_null($dsid) ? $dsid : array($dsid);
islandora_scholar_embargo_lift_embargo($pid, $dsids);
islandora_scholar_embargo_set_embargo($pid, $dsids, $embargoed_item['expiry']['value']);
$sandbox['completed']++;
$sandbox['slice']['offset_date'] = $embargoed_item['date']['value'];
$sandbox['slice']['offset_pid'] = $pid;
$context['message'] = t('@count/@total: Re-applied embargo to @item of @pid.', array(
'@count' => $sandbox['completed'],
'@total' => $sandbox['total'],
'@item' => is_null($dsid) ? t('entire object') : $dsid,
'@pid' => $pid,
));
}
// If the set was empty, $context['finished'] will be 1 anyway.
$context['finished'] == $sandbox['completed'] / $sandbox['total'];
}
if ($context['finished'] >= 1) {
drupal_set_message(t('Re-applied embargoes to @total objects.', array(
'@total' => $sandbox['completed'],
)));
}
}
}
74 changes: 62 additions & 12 deletions modules/islandora_scholar_embargo/includes/embargo.inc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function islandora_scholar_embargo_form(array $form, array &$form_state, Abstrac
// Table seems somewhat of overkill for now, but as the embargo offering
// grows more robust this sort of formatting for the UI will make sense.
$rows = array();
$current_embargos = array();
$current_embargoes = array();
$date = '';
foreach ($embargo_results as $result) {
if ($result['obj']['value'] == $item->id) {
Expand All @@ -52,12 +52,12 @@ function islandora_scholar_embargo_form(array $form, array &$form_state, Abstrac
$type,
$date,
);
$current_embargos[] = array(
$current_embargoes[] = array(
'type' => $type,
'date' => $date,
);
}
$form_state['islandora_embargo'] = $current_embargos;
$form_state['islandora_embargo'] = $current_embargoes;
$embargoed = TRUE;
if (empty($embargo_results)) {
$embargoed = FALSE;
Expand Down Expand Up @@ -150,7 +150,7 @@ function islandora_scholar_embargo_form(array $form, array &$form_state, Abstrac
'#title' => check_plain($embargoed ? t('Update Options') : t('Embargo Options')),
'#options' => array(
'change_embargo_date' => $embargoed ? t('Change the embargo date') : t('Set the embargo date'),
'indefinite_embargo' => t('Embargo indefinitely (Indefinite embargos must be lifted manually).'),
'indefinite_embargo' => t('Embargo indefinitely (Indefinite embargoes must be lifted manually).'),
),
'#default_value' => ($date === 'Indefinite') ? 'indefinite_embargo' : 'change_embargo_date',
'#states' => array(
Expand Down Expand Up @@ -265,7 +265,7 @@ function islandora_scholar_embargo_form_validate(array $form, array &$form_state
$parsed = strtotime($parsed_date);
if ($embargoed) {
// This will need to be updated in the future to handle multiple
// embargos on a single object.
// embargoes on a single object.
foreach ($form_state['islandora_embargo'] as $embargo_vals) {
$embargo_date = $embargo_vals['date'];
break;
Expand All @@ -279,7 +279,7 @@ function islandora_scholar_embargo_form_validate(array $form, array &$form_state
}
}
elseif ($form_state['values']['update_date_options'] === 'indefinite_embargo') {
// This will need to be updated in the future to handle multiple embargos
// This will need to be updated in the future to handle multiple embargoes
// on a single object.
$embargo_date = '';
foreach ($form_state['islandora_embargo'] as $embargo_vals) {
Expand Down Expand Up @@ -390,7 +390,7 @@ function islandora_scholar_embargo_form_submit(array $form, array &$form_state)
}
}
// Currently we just overwrite what's already in place. In the future, for
// multiple embargos on a single object, this will have to be adjusted.
// multiple embargoes on a single object, this will have to be adjusted.

// If we're recursing do those objects in a batch.
if (isset($form_state['values']['recurse']) && $form_state['values']['recurse'] && $form_state['values']['recurse_options'] != 'newchildren') {
Expand Down Expand Up @@ -445,24 +445,74 @@ EOQ;
}

/**
* Retrieve all embargoed items from an object.
* Retrieve all embargoed items.
*
* @param bool $count
* Whether or not to just return the total count.
*
* @return array
* An array containing the list of embargoed items on an object
* An array containing the list of embargoed items.
*/
function islandora_scholar_embargo_get_all_embargoed() {
function islandora_scholar_embargo_get_all_embargoed($count = FALSE) {
$current_embargo = <<<EOQ
PREFIX is: <info:islandora/islandora-system:def/scholar#>
SELECT ?obj ?date
FROM <#ri>
WHERE {
?obj is:embargo-until ?date
}
EOQ;
if ($count) {
$current_embargo .= <<<EOQ
ORDER BY ?obj
EOQ;
}
$connection = islandora_get_tuque_connection();
$embargo_results = $connection->repository->ri->sparqlQuery($current_embargo, 'unlimited', '0');
return $embargo_results;
$ri = $connection->repository->ri;
return $count ? $ri->countQuery($current_embargo, 'sparql') : $ri->sparqlQuery($current_embargo, 'unlimited', '0');
}

/**
* Gets a subset of all embargoed items.
*
* @param array $slice_params
* An associative array containing:
* 'offset_date': an ISO8601 datetime to filter items before
* 'offset_pid': a PID to filter on when a date match is found.
* @param int $limit
* The number of items to return in the subset.
*
* @return array
* A SPARQL query results array containing a subset of embargoed items,
* including 'obj' as the object ID, 'expiry' as the expiry date, and 'date'
* as the item's created or last modified date.
*/
function islandora_scholar_embargo_get_embargoed_items_subset($slice_params = array(), $limit = 10) {
// Build the query.
$current_embargo = <<<EOQ
PREFIX is: <info:islandora/islandora-system:def/scholar#>
PREFIX xs: <xml-schema:>
SELECT DISTINCT ?obj ?expiry ?date
FROM <#ri>
WHERE {
?obj is:embargo-until ?expiry ;
{ ?obj <fedora-model:createdDate> ?date } UNION
{ ?obj <fedora-view:lastModifiedDate> ?date ;
<fedora-view:disseminationType> ?dsid
}
EOQ;
// Offset if asked.
if ($slice_params) {
$current_embargo .= "FILTER(?date > '{$slice_params['offset_date']}'^^xs:dateTime || (?date = '{$slice_params['offset_date']}'^^xs:dateTime && xs:string(?obj) > xs:string('info:fedora/{$slice_params['offset_date']}')))";
}
$current_embargo .= <<<EOQ
}
ORDER BY ASC(?date) ASC(?obj)
EOQ;

// Use the query.
$connection = islandora_get_tuque_connection();
return $connection->repository->ri->sparqlQuery($current_embargo, $limit);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/**
* @file
* Admin form for setting embargo view/manage roles.
*/

/**
* Embargo roles admin management form.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*
* @return array
* The form definition.
*/
function islandora_scholar_embargo_manage_roles_admin_form($form, $form_state) {
module_load_include('inc', 'islandora_scholar_embargo', 'includes/embargo');
return array(
'roles_wrapper' => array(
'#type' => 'fieldset',
'#title' => t('Roles'),
'#collapsible' => FALSE,
'islandora_scholar_embargo_whitelisted_roles' => array(
'#type' => 'checkboxes',
'#description' => t('Check off all the roles that should have access to embargoed items. <strong>NOTE:</strong> since embargo XACML role entries are whitelists, embargoed objects in a Fedora repository shared between Drupal sites will be visible to the same role in both sites. Consider using site-unique roles when dealing with shared repositories.'),
'#options' => user_roles(TRUE, ISLANDORA_SCHOLAR_EMBARGO_CAN_EMBARGO_ANY),
'#default_value' => array_keys(variable_get('islandora_scholar_embargo_whitelisted_roles', array())),
),
),
'note' => array(
'#markup' => t('Saving and applying will initiate a batch to modify the XACML policies of all embargoed objects. Bear in mind that this can take a long time to execute depending on the number of items to be embargoed, and that it may be more prudent to run the Drush command <code>islandora_scholar_embargo_apply_roles_to_embargoed_objects</code> instead. Number of embargoed objects at time of page load: <strong>@number</strong>', array(
'@number' => number_format(islandora_scholar_embargo_get_all_embargoed(TRUE)),
)),
),
'submit_buttons' => array(
'#type' => 'actions',
'save' => array(
'#type' => 'submit',
'#value' => t('Save Without Applying'),
'#name' => 'save',
),
'save_and_apply' => array(
'#type' => 'submit',
'#value' => t('Save And Apply'),
'#name' => 'save_and_apply',
),
),
);
}

/**
* Submit handler for the roles management form.
*
* @param array $form
* The submitted roles admin form.
* @param array $form_state
* The state of the submitted form.
*/
function islandora_scholar_embargo_manage_roles_admin_form_submit($form, &$form_state) {
// Attach role names to role IDs to make it more useful as a variable.
$whitelist = array();
foreach (array_filter($form_state['values']['islandora_scholar_embargo_whitelisted_roles']) as $rid => $checked) {
$whitelist[$rid] = $form['roles_wrapper']['islandora_scholar_embargo_whitelisted_roles']['#options'][$rid];
}
variable_set('islandora_scholar_embargo_whitelisted_roles', $whitelist);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing variable_del() for the new variable?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whooops

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, still?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 420aa12


// Kick off the batch if we were asked.
if ($form_state['triggering_element']['#name'] == 'save_and_apply') {
module_load_include('inc', 'islandora_scholar_embargo', 'includes/batch');
batch_set(islandora_scholar_embargo_reapply_embargoes_batch());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ function islandora_scholar_embargo_drush_command() {
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
'callback' => 'islandora_scholar_embargo_lift_embargoes_update',
),
'islandora_scholar_embargo_reapply_embargoes' => array(
'description' => dt('Applies the list of roles that can administer embargoes to all embargoed objects in the repository.'),
'examples' => array('drush -v -u 1 islandora_scholar_embargo_reapply_embargoes'),
'aliases' => array('ise-reapply'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
'callback' => 'islandora_scholar_embargo_reapply_embargoes',
),
);
}

Expand All @@ -44,6 +51,15 @@ function islandora_scholar_embargo_lift_embargoes_update() {
drush_backend_batch_process();
}

/**
* Runs the batch to apply whitelisted roles to embargoed objects.
*/
function islandora_scholar_embargo_reapply_embargoes() {
module_load_include('inc', 'islandora_scholar_embargo', 'includes/batch');
batch_set(islandora_scholar_embargo_reapply_embargoes_batch());
drush_backend_batch_process();
}

/**
* Batch operation for lifting embargoes for the update.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
function islandora_scholar_embargo_uninstall() {
$variables = array(
'islandora_embargo_content_models',
'islandora_scholar_embargo_whitelisted_roles',
);
array_walk($variables, 'variable_del');
}
Expand Down
Loading