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 ${file['filename']} 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 = ' '. theme_image(drupal_get_path('module', 'Fedora_Repository') . '/images/view.gif', '', 'View the item\'s repository page' ) . ''; } $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); }