You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
491 lines
19 KiB
491 lines
19 KiB
<?php |
|
// $Id$ |
|
|
|
/** |
|
* Implementation of hook_perm() |
|
* |
|
* @return Array of permissions defined in this module. |
|
*/ |
|
function fedora_attach_perm() { |
|
return array( |
|
'select file access by role', |
|
); |
|
} |
|
|
|
/** |
|
* Implementation of hook_nodeapi. |
|
* On Update and Insert operations alters the file attach form to add option to ingest into fedora. |
|
* On View option hilights files that are in the repository. |
|
*/ |
|
function fedora_attach_nodeapi(&$node, $op, $teaser) { |
|
module_load_include('inc', 'fedora_repository', 'api/fedora_item'); |
|
module_load_include('inc','fedora_repository','api/fedora_utils.inc'); |
|
switch ($op) { |
|
case 'insert': |
|
case 'update': |
|
// ****************************************************** |
|
// *** INSERT/UPDATE |
|
// *** Ingest a selected file into the repository. |
|
// ****************************************************** |
|
if (user_access('upload files') && user_access('add fedora datastreams')) { |
|
if (is_array($node->files)) { |
|
foreach ($node->files as $fid => $file) { |
|
$file = (object) $file; // Convert file to object type for compatibility. |
|
$fid = $file->fid; // For the cases where we have temp fid for uplaoded files. |
|
$success = FALSE; |
|
$filepath = $file->filepath; // Need copy if file_move fails. |
|
$public = file_directory_path(); |
|
|
|
$file_is_ingested = _fedora_attach_is_file_in_repository($filepath); |
|
if (!empty($file->ingested) && !$file_is_ingested) { |
|
// Attach flag is set, but file is not listed as being in the repository. |
|
// so try and ingest it now. |
|
if (user_access('select file access by role')) { |
|
$roles = array(); |
|
if (!empty($file->roles)) { |
|
foreach ($file->roles as $rolename => $rolevalue) { |
|
if (!empty($rolevalue)) { |
|
array_push($roles, $rolevalue); |
|
} |
|
} |
|
} |
|
// if (!empty($roles)) { |
|
// Generate the security policy datastream. |
|
$policy_stream = _fedora_attach_create_policy($roles); |
|
// } |
|
} |
|
try { |
|
$pid_namespace = variable_get('fedora_attach_pid_namespace','default:'); |
|
$pid_namespace = substr($pid_namespace, 0, strpos($pid_namespace, ":")); |
|
$pid = fedora_item::get_next_PID_in_namespace( $pid_namespace ); |
|
$new_item = fedora_item::ingest_new_item($pid, 'A', $file->description); // PID will be generated using getNextPID |
|
if (empty($new_item->objectProfile)) { |
|
drupal_set_message("Unable to create fedora object. Check Watchdog log for details.", "error"); |
|
$success = FALSE; |
|
} |
|
else { |
|
if (user_access('select file access by role')) { |
|
$new_item->add_datastream_from_string($policy_stream, 'POLICY', "Security Policy", "text/xml", "X"); |
|
} |
|
$new_item->add_datastream_from_file($file->filepath, 'OBJ', $file->filename, $file->filemime, 'M'); |
|
$new_item->add_relationship("hasModel","islandora:genericCModel",FEDORA_MODEL_URI); |
|
module_load_include('inc', 'fedora_repository', 'api/dublin_core'); |
|
$dc = new Dublin_Core(); |
|
$dc->add_element('dc:title', $file->description); |
|
$dc->add_element('dc:identifier', $new_item->pid); |
|
|
|
$new_item->modify_datastream_by_value($dc->as_xml(), 'DC', 'Default Dublin Core Metadata', 'text/xml', 'X'); |
|
|
|
$success = TRUE; |
|
} |
|
} |
|
catch (exception $e) { |
|
drupal_set_message(t('An error occurred ingesting the file: ') . $e, 'error'); |
|
$new_item->purge(); |
|
drupal_set_message(t('The item has been removed from the repository')); |
|
} |
|
if ($success) { // We were able to ingest the file, so update the file path. |
|
$new_filepath = '/fedora/repository/'. $new_item->pid . '/OBJ/'. $file->description; |
|
_fedora_attach_update_filepath($new_filepath, $fid); |
|
file_delete($filepath); |
|
} |
|
} |
|
// Convert file to object for compatibility |
|
|
|
// Remove file. Process removals first since no further processing |
|
// will be required. |
|
if (!empty($file->remove)) { |
|
|
|
// If the file isn't used by any other revisions warn the user. |
|
$count = db_result(db_query('SELECT COUNT(fid) FROM {upload} WHERE fid = %d', $fid)); |
|
if ($count < 1) { |
|
file_delete($file->filepath); |
|
db_query('DELETE FROM {files} WHERE fid = %d', $fid); |
|
} |
|
|
|
// Remove it from the session in the case of new uploads, |
|
// that you want to disassociate before node submission. |
|
unset($node->files[$fid]); |
|
// Move on, so the removed file won't be added to new revisions. |
|
continue; |
|
} |
|
|
|
} |
|
} |
|
} |
|
break; |
|
case 'view': |
|
// ****************************************************** |
|
// *** VIEW |
|
// Re-theme the file attachments table. |
|
|
|
// Rebuild the files table and overwrite default. |
|
// Using the rules from upload.module. |
|
if (isset($node->files) && count($node->files) && user_access('view uploaded files') && !$teaser) { |
|
$node->content['files']['#value'] = theme('fedora_attach_attachments', $node->files); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
/** |
|
*Implementation of hook_menu(). |
|
*/ |
|
function fedora_attach_menu() { |
|
$items['admin/settings/fedora_repository/attach'] = array( |
|
'title' => 'Fedora Attach', |
|
'page callback' => 'drupal_get_form', |
|
'page arguments' => array('fedora_attach_admin'), |
|
'access arguments' => array('administer site configuration'), |
|
'type' => MENU_LOCAL_TASK, |
|
'file' => 'fedora_attach.admin.inc', |
|
); |
|
return $items; |
|
} |
|
|
|
|
|
function fedora_attach_save(&$node) { |
|
print ("FNARF!"); |
|
} |
|
|
|
/** |
|
* Implements hook_form_alter() |
|
* |
|
* Add a 'add to repository' checkbox to the file attach form. |
|
* |
|
* @param unknown_type $form |
|
* @param unknown_type $form_state |
|
* @param unknown_type $form_id |
|
* Two paths, one for normal submit, one for JavaScript |
|
*/ |
|
function fedora_attach_form_alter(&$form, $form_state, $form_id) { |
|
$disabled = TRUE; |
|
global $base_url; |
|
if (isset($form['type'])) { |
|
$node = $form['#node']; |
|
if ($form['type']['#value'] . '_node_form' == $form_id && variable_get("upload_$node->type", TRUE)) { |
|
$form['#submit'][] = 'fedora_attach_form_submit'; |
|
if (!empty($node->files) && is_array($node->files) && count($node->files)) { // Hijack theme function. |
|
$form['attachments']['wrapper']['files']['#theme'] = 'fedora_attach_form'; |
|
$form['#validate']['private_upload_form_validate'] = array(); |
|
foreach ($node->files as $fid => $file) { |
|
|
|
// Add ingest checkbox |
|
if (is_array($file) && isset($file['ingest'])) { // Preview |
|
$default_value = $file['ingest']; |
|
} |
|
else { // Node load |
|
$default_value = _fedora_attach_is_file_in_repository($file->filepath); |
|
$disabled = $default_value; |
|
} |
|
|
|
$form['attachments']['wrapper']['files'][$fid]['ingested'] = array( |
|
'#type' => 'checkbox', |
|
'#default_value' => $default_value, |
|
'#disabled' => $disabled, |
|
); |
|
$form['attachments']['wrapper']['files'][$fid]['description']['#description'] = $base_url.$file->filepath; |
|
} |
|
if (user_access('select file access by role')) { |
|
_fedora_attach_build_roles_form($form, FALSE); |
|
} |
|
} |
|
} |
|
} |
|
elseif ($form_id == 'upload_js') { |
|
$form['files']['#theme'] = 'fedora_attach_form'; |
|
|
|
foreach ($form['files'] as $fid => $file) { |
|
|
|
if (!_fedora_attach_starts_with($fid, '#')) {// Ignore properties. |
|
if (!empty($_POST['files'][$fid])) { |
|
$ingested = (!empty($_POST['files'][$fid]['ingested']) ? $_POST['files'][$fid]['ingested'] : FALSE); |
|
//$form['files'][$fid]['list']['#default_value'] = (!empty($_POST['files'][$fid]['[$_POST['files'][$fid]['list']; |
|
//$form['files'][$fid]['remove']['#default_value'] = $_POST['files'][$fid]['remove']; |
|
} |
|
else { |
|
$ingested = (variable_get('fedora_attach_default', 'ingested') == 'ingested'); |
|
} |
|
$form['files'][$fid]['ingested'] = array( |
|
'#type' => 'checkbox', |
|
'#default_value' => $ingested, |
|
); |
|
|
|
$form['attachments']['wrapper']['files'][$fid]['description']['#description'] = $base_url.$file['filepath']; |
|
if (user_access('select file access by role')) { |
|
_fedora_attach_build_roles_form($form, TRUE); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Called to validate the attach form. |
|
* |
|
* @param string $formid |
|
* @param array $form_values |
|
*/ |
|
function fedora_attach_form_validate($formid, $form_values) { |
|
if (is_array($form_values['files']) && count($form_values['files'])) { |
|
$file = array_shift($form_values['files']); |
|
if (!isset($file['ingested'])) { |
|
drupal_set_message(t('Fedora Attach cannot find add repository settings.'), 'error'); |
|
// Be sure we are going after core upload module |
|
$upload_weight = (int)db_result(db_query("SELECT weight FROM {system} WHERE name = 'upload'")); |
|
$attach_weight = (int)db_result(db_query("SELECT weight FROM {system} WHERE name = 'fedora_attach'")); |
|
if ($attach_weight <= $uplaod_weight) { |
|
$new_weight = $upload_weight + 1; |
|
drupal_set_message(t('Adjusting Fedora Attach module\'s weight to') . $new_weight, 'warning'); |
|
db_query("UPDATE {system} SET weight = '%d' WHERE name = 'fedora_attach'", $new_weight);; |
|
} |
|
else { |
|
drupal_set_message(t('Please check for modules that conflict with Fedora Attach'), 'error'); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Fixes edge case: When the node is first being created, the file->private info does not |
|
* get moved automatically into the node. So we need to copy it by hand. |
|
* |
|
* @param array $form |
|
* @param array $form_state |
|
*/ |
|
function fedora_attach_form_submit($form, &$form_state) { |
|
global $base_url; |
|
if ($form_state['values'] && $form_state['values']['files']) { |
|
|
|
foreach ($form_state['values']['files'] as $fid => $file) { |
|
if ($file['remove'] && !empty($file['ingested']) && $file['ingested']) { |
|
drupal_set_message("The attachment <a href=\"$base_url/". substr($file['filepath'], 0, strpos($file['filepath'], 'OBJ'))."\">${file['filename']}</a> was removed from this node but it will remain in the repository until it is purged it directly."); |
|
} |
|
if (!isset($file->ingested)) { // Newly-inserted file. |
|
if (isset($form['attachments']['wrapper']['files'])) { |
|
// I know it is naughty to look at the $_POST, but I can't find this value anywhere else. |
|
// Seems like it should be in $form_state somewhere. |
|
$ingested = !empty($_POST['files'][$fid]['ingested']); |
|
} |
|
else { |
|
$ingested = (variable_get('fedora_attach_ingested', 'ingested') == 'ingested'); // Submit before attach |
|
} |
|
$form_state['values']['files'][$fid]['ingested'] = $ingested; |
|
} |
|
$form_state['values']['files'][$fid]['roles'] = (!empty($_POST['files']['roles']) ? $_POST['files']['roles'] : array()); |
|
} |
|
} |
|
} |
|
|
|
// ***************************************************************************** |
|
// Theme functions *********************************************************** |
|
// ***************************************************************************** |
|
|
|
/** |
|
* hook_theme = Theme registry |
|
* |
|
* @return array |
|
*/ |
|
function fedora_attach_theme() { |
|
return array( |
|
'fedora_attach_form' => array( |
|
'arguments' => array('form' => NULL), |
|
), |
|
'fedora_attach_attachments' => array( |
|
'arguments' => array('files' => NULL), |
|
), |
|
); |
|
} |
|
|
|
/** |
|
* Based on theme_upload_form_current |
|
* Adds the Ingest checkbox. |
|
* |
|
* @param array $form |
|
*/ |
|
function theme_fedora_attach_form(&$form) { |
|
$header = array(t('Delete'), t('List'), t('Add to Repository'), t('Label'), t('Weight'), t('Size'), ''); |
|
drupal_add_tabledrag('upload-attachments', 'order', 'sibling', 'upload-weight'); |
|
|
|
foreach (element_children($form) as $key) { |
|
// Add class to group weight fields for drag and drop. |
|
$form[$key]['weight']['#attributes']['class'] = 'upload-weight'; |
|
|
|
$row = array(); |
|
$row[] = drupal_render($form[$key]['remove']); |
|
$row[] = drupal_render($form[$key]['list']); |
|
$row[] = drupal_render($form[$key]['ingested']); |
|
$row[] = drupal_render($form[$key]['description']); |
|
$row[] = drupal_render($form[$key]['weight']); |
|
$row[] = drupal_render($form[$key]['size']); |
|
$row[] = drupal_render($form[$key]['msg']); |
|
$rows[] = array('data' => $row, 'class' => 'draggable'); |
|
} |
|
$output = theme('table', $header, $rows, array('id' => 'upload-attachments')); |
|
$output .= drupal_render($form); |
|
return $output; |
|
} |
|
|
|
/** |
|
* Displays file attachments in table. |
|
* |
|
* @param array $files |
|
*/ |
|
function theme_fedora_attach_attachments($files) { |
|
$header = array(t('Attachment'), t('Size')); |
|
$rows = array(); |
|
if (is_array($files)) { |
|
foreach ($files as $file) { |
|
$file = (object) $file; |
|
if ($file->list && empty($file->remove)) { |
|
$inspect_item = ''; |
|
if (_fedora_attach_is_file_in_repository($file->filepath)) { |
|
$inspect_item = ' <a href="'. $GLOBALS['base_url'] . substr($file->filepath, 0, strpos($file->filepath, 'OBJ')) . |
|
'">'. theme_image(drupal_get_path('module', 'Fedora_Repository') . '/images/view.gif', '', 'View the item\'s repository page' ) . '</a>'; |
|
} |
|
$href = _fedora_attach_create_url($file); // this is the changed line |
|
$text = $file->description ? $file->description : $file->filename; |
|
$rows[] = array(l($text, $href) . $inspect_item, format_size($file->filesize)); |
|
} |
|
} |
|
if (count($rows)) { |
|
return theme('table', $header, $rows, array('id' => 'attachments')); |
|
} |
|
} |
|
} |
|
|
|
function _fedora_attach_build_roles_form(&$form, $inside_js = FALSE) { |
|
//$result = db_query("SELECT {name} from {role}"); |
|
global $user; |
|
//while ($role = db_fetch_array($result)) { |
|
foreach ($user->roles as $role) { |
|
if ($role != 'anonymous user') { |
|
$roles[] = $role; |
|
} |
|
} |
|
if (empty($roles)) { |
|
return ''; |
|
} |
|
$new_form_elements = array( |
|
'#type' => 'checkboxes', |
|
'#title' => t('Roles which can view the attached items'), |
|
'#options' => array_combine($roles, $roles), |
|
'#description' => t('This only applies to files which you add to the repository. If no roles are checked the item will be public.'), |
|
); |
|
|
|
if ($inside_js) { |
|
$form['files']['roles'] = $new_form_elements; |
|
} |
|
else { |
|
$form['attachments']['wrapper']['roles'] = $new_form_elements; |
|
} |
|
// var_dump($form['files']); |
|
//return $output; |
|
} |
|
|
|
function _fedora_attach_create_policy($roles) { |
|
$policy_filename = !empty($roles) ? drupal_get_path('module', 'fedora_repository') . '/policies/viewANDeditbyrole.xml' |
|
: drupal_get_path('module', 'fedora_repository') . '/policies/noObjectEditPolicy.xml'; |
|
$policy_document = new DOMDocument(); |
|
$policy_document->load($policy_filename); |
|
$designators = $policy_document->getElementsByTagName("SubjectAttributeDesignator"); |
|
|
|
if (!empty($designators)) { |
|
foreach ($designators as $designator) { |
|
if ($designator->hasAttribute("AttributeId")) { |
|
if ($designator->getAttribute('AttributeId') == 'fedoraRole') { |
|
foreach ($roles as $role) { |
|
//$apply = $designator->nextSibling; |
|
foreach ($designator->parentNode->childNodes as $apply) { |
|
if ($apply->nodeName == "Apply") { |
|
$new_role_node = $policy_document->createElement('AttributeValue', $role); |
|
$new_role_node->setAttribute('DataType', 'http://www.w3.org/2001/XMLSchema#string'); |
|
$apply->appendChild($new_role_node); |
|
} |
|
} |
|
} |
|
} |
|
elseif ($designator->getAttribute('AttributeId') == 'urn:fedora:names:fedora:2.1:subject:loginId') { |
|
// $apply = $designator->nextSibling; |
|
foreach ($designator->parentNode->childNodes as $apply) { |
|
if ($apply->nodeName == "Apply") { |
|
global $user; |
|
$new_user_node = $policy_document->createElement('AttributeValue', $user->name); |
|
$new_user_node->setAttribute('DataType', 'http://www.w3.org/2001/XMLSchema#string'); |
|
$apply->appendChild($new_user_node); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return $policy_document->saveXML(); |
|
} |
|
|
|
function fedora_attach_file_download($filepath) { |
|
// Pass through if this isn't a repository item. |
|
if (!strstr($filepath, 'fedora/repository')) { |
|
return; |
|
} |
|
$result = db_query("SELECT DISTINCT(u.nid) FROM {upload} u INNER JOIN {files} f ON u.fid = f.fid ". |
|
"WHERE f.filepath LIKE '%s'", $filepath.'%'); |
|
$has_results = FALSE; |
|
while($row = db_fetch_array($result)) { |
|
$has_results = TRUE; |
|
$node = node_load($row['nid']); |
|
if (node_access('view', $node)) { |
|
return; // Access is ok as far as we are concerned. |
|
} |
|
} |
|
if ($has_results) { |
|
return -1; |
|
} |
|
else { |
|
return; |
|
} |
|
} |
|
|
|
/** |
|
* Create a URL to a file that changes if the file is in the repository. |
|
* |
|
* @param file object $file |
|
* @return str: the correct URL |
|
*/ |
|
function _fedora_attach_create_url($file) { |
|
if ( _fedora_attach_is_file_in_repository( $file->filepath)) { |
|
$href = $GLOBALS['base_url'] . $file->filepath; |
|
} |
|
else { |
|
$href = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path()))); |
|
} |
|
return $href; |
|
} |
|
|
|
/** |
|
* Checks if the file path references a file in the repository. |
|
* |
|
* @param string $filepath |
|
* @return boolean |
|
*/ |
|
function _fedora_attach_is_file_in_repository($filepath) { |
|
$repository_path = '/fedora/repository'; |
|
$is_in = _fedora_attach_starts_with($filepath, $repository_path); |
|
return $is_in; |
|
} |
|
|
|
function _fedora_attach_starts_with($str, $start) { |
|
if (count($str) == 0) { // Avoid FALSE positives. |
|
return FALSE; |
|
} |
|
return strstr($str, $start) == $str; |
|
} |
|
|
|
/** |
|
* Alters the file's path in the files table to point to the repository datastream. |
|
* |
|
* @param string $filepath |
|
* @param int $fid |
|
*/ |
|
function _fedora_attach_update_filepath( $filepath, $fid ) { |
|
db_query("UPDATE {files} SET filepath = '%s' WHERE fid=%d", $filepath, $fid); |
|
}
|
|
|