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.
492 lines
19 KiB
492 lines
19 KiB
14 years ago
|
<?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);
|
||
|
}
|