diff --git a/CollectionClass.inc b/CollectionClass.inc index 5882a460..b027ac4c 100644 --- a/CollectionClass.inc +++ b/CollectionClass.inc @@ -28,11 +28,9 @@ class CollectionClass { * @return CollectionClass */ function __construct($pid = NULL) { - if (!empty($pid)) { - module_load_include('inc', 'fedora_repository', 'ObjectHelper'); - $this->collectionObject = new ObjectHelper($pid); - $this->pid = $pid; - } + module_load_include('inc', 'fedora_repository', 'ObjectHelper'); + $this->collectionObject = new ObjectHelper(); + $this->pid = $pid; } public static function getCollectionQuery($pid) { @@ -672,6 +670,79 @@ class CollectionClass { return $page; } + /** + * Assemble results in a somewhat more logical manner... + * + * ... Compared to generating a table in XSLT to contain a list (as + * renderCollection() used to do/does by default). + * + * @param $sparql_results array + * The array of results as yielded by ObjectHelper::parseSparqlResults() + * (and those associated functions which make use of it) + * @return + * An array to be passed to drupal_render, containing a pager, an unordered + * list of items, and another pager. + */ + public static function assembleCollectionView($sparql_results) { + $per_page = 20; //XXX: Make this configurable. + $pager_name = 0; + $total = count($sparql_results); + $pager_page = self::hackPager($pager_name, $per_page, $total); + $max_title_length = 60; + + $results = array(); + foreach (array_slice($sparql_results, $per_page * $pager_page, $per_page) as $result) { + $title = $result['title']; + $truncated_title = truncate_utf8($title, $max_title_length, TRUE, TRUE, 5); + $obj_path = "fedora/repository/{$result['object']}"; + $tn_path = ($result['thumbnail'] ? + "fedora/repository/{$result['thumbnail']}": + "$obj_path/TN"); + + $thumbnail = theme('image', $tn_path, $truncated_title, $title, array(), FALSE); + + $results[] = array( + 'data' => l($thumbnail, $obj_path, array( + 'html' => TRUE, + 'attributes' => array( + 'class' => 'results-image', + ), + )) . l($truncated_title, $obj_path, array('attributes' => array('class' => 'results-text'))), + ); + } + if (!$results) { + drupal_set_message(t("No objects in this collection (or bad query).")); + } + else { + $first = $per_page * $pager_page; + $last = (($total - $first) > $per_page)? + ($first + $per_page): + $total; + $results_range_text = t('Results @first to @last of @total', array( + '@first' => $first + 1, + '@last' => $last, + '@total' => $total, + )); + + return array( + array( + '#type' => 'markup', + '#value' => theme('pager', array(), $per_page, $pager_name), + ), + array( + '#type' => 'markup', + '#value' => theme('item_list', $results, $result_range_text, 'ul', array( + 'class' => 'islandora-collection-results-list', + )) + ), + array( + '#type' => 'markup', + '#value' => theme('pager', array(), $per_page, $pager_name) + ), + ); + } + } + /** * render collection * @global type $base_url @@ -703,48 +774,13 @@ class CollectionClass { $objectList = ''; if (isset($content) && $content != FALSE) { if (!$xslContent) { //Didn't find an XSLT. - $intermediate_results = ObjectHelper::parse_sparql_results($content); - unset($content); - - $per_page = 20; //XXX: Make this configurable. - $pager_name = 0; - $total = count($intermediate_results); - $pager_page = self::hackPager($pager_name, $per_page, $total); - - $results = array(); - foreach (array_slice($intermediate_results, $per_page * $pager_page, $per_page) as $result) { - $title = $result['title']; - $obj_path = "fedora/repository/{$result['object']}"; - $thumbnail = theme('image', "$obj_path/TN", $title, $title, array(), FALSE); - $results[] = array( - 'data' => l($thumbnail, $obj_path, array( - 'html' => TRUE, - 'attributes' => array( - 'class' => 'results-image', - ), - )) . l($title, $obj_path, array('attributes' => array('class' => 'results-text'))), - ); - } - if (!$results) { - drupal_set_message(t("No objects in this collection (or bad query).")); - } - else { - $first = $per_page * $pager_page; - $last = (($total - $first) > $per_page)? - ($first + $per_page): - $total; - $results_range_text = t('Results @first to @last of @total', array( - '@first' => $first + 1, - '@last' => $last, - '@total' => $total, - )); - //$objectList = '

' . $results_range_text . '

'; - $objectList .= theme('pager', array(), $per_page, $pager_name); - $objectList .= theme('item_list', $results, $result_range_text, 'ul', array( - 'class' => 'islandora-collection-results-list', - )); - $objectList .= theme('pager', array(), $per_page, $pager_name); - } + return drupal_render( + self::assembleCollectionView( + $this->collectionObject->parseSparqlResults( + $content + ) + ) + ); } else { if (!$pageNumber) { diff --git a/MimeClass.inc b/MimeClass.inc index 42c11e37..b2950f6e 100644 --- a/MimeClass.inc +++ b/MimeClass.inc @@ -231,9 +231,7 @@ class MimeClass { * @return type */ public function get_mimetype($filename, $debug = FALSE) { - - $file_name_and_extension = explode('.', $filename); - $ext = strtolower(array_pop($file_name_and_extension)); + $ext = strtolower(substr($filename, strrpos($filename, '.') + 1)); if (!empty($this->private_mime_types[$ext])) { if (TRUE === $debug) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index e866f62f..3c54661e 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -2,7 +2,7 @@ /** - * @file + * @file * Object Helper Class */ @@ -32,8 +32,17 @@ class ObjectHelper { drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); module_load_include('inc', 'fedora_repository', 'ConnectionHelper'); $connectionHelper = new ConnectionHelper(); - //$this->fedoraUser = $connectionHelper->getUser(); - //$this->fedoraPass = $connectionHelper->getPassword(); + } + + private static function getBinaryLength($bin) { + $has_mbstring = extension_loaded('mbstring') ||@dl(PHP_SHLIB_PREFIX.'mbstring.'.PHP_SHLIB_SUFFIX); + $has_mb_shadow = (int) ini_get('mbstring.func_overload'); + + if ($has_mbstring && ($has_mb_shadow & 2) ) { + return mb_strlen($bin,'latin1'); + } else { + return strlen($bin); + } } /** @@ -72,7 +81,6 @@ class ObjectHelper { return ' '; } - if (variable_get('fedora_object_restrict_datastreams', FALSE) == TRUE) { if (($cm = ContentModel::loadFromObject($pid)) == FALSE) { drupal_set_message(t("You do not have access to objects without an Islandora Content Model."), 'error'); @@ -91,7 +99,6 @@ class ObjectHelper { module_load_include('inc', 'fedora_repository', 'api/fedora_item'); $item = new Fedora_Item($pid); - if (isset($item->datastreams[$dsID])) { $mimeType = $item->datastreams[$dsID]['MIMEType']; if ($label == NULL) { @@ -107,24 +114,24 @@ class ObjectHelper { if ((!isset($user)) || $user->uid == 0) { $fedoraUser = 'anonymous'; $fedoraPass = 'anonymous'; - $contentSize = 0; - } - else { + } else { $fedoraUser = $user->name; $fedoraPass = $user->pass; - $dataStreamInfo = $item->get_datastream_info($dsID); - $contentSize = $dataStreamInfo->datastream->size; } + + $dataStreamInfo = $item->get_datastream_info($dsID); + $contentSize = $dataStreamInfo->datastream->size; if (function_exists("curl_init")) { - if (!isset($mimeType)) { - $pid = variable_get('fedora_default_display_pid', 'demo:10'); - $dsID = variable_get('fedora_default_display_dsid', 'TN'); - $mimeType = 'image/jpeg'; - } $url = variable_get('fedora_base_url', 'http://localhost:8080/fedora') . '/objects/' . $pid . '/datastreams/' . $dsID . '/content'; + $query_options = array(); if ($version) { - $url .= '/' . $version; //drupal_urlencode($version); + $query_options['asOfDateTime'] = $version; //drupal_urlencode($version); + } + if ($query_options) { + $url = url($url, array( + 'query' => $query_options, + )); } $ch = curl_init(); $user_agent = "Mozilla/4.0 pp(compatible; MSIE 5.01; Windows NT 5.0)"; @@ -150,42 +157,47 @@ class ObjectHelper { fclose($fp); } else { - header("Content-type: $mimeType"); - if ($contentSize > 0) { - header("Content-length: $contentSize"); - } - - if ($asAttachment) { - $suggestedFileName = "$label"; - $pos = strpos($suggestedFileName, '.'); - - /* - * Here we used to take an object of, say, type application/pdf with label, say, "My Document" - * and we assemble the output filename extension based on the post-slash portion of the mimetype. - * (If the label has a period anywhere in it, we leave it alone.) - * - * This is great for simple mimetypes like application/pdf, text/html, image/jpeg, etc. - * but it's terrible for, say, application/vnd.oasis.opendocument.text (.odt). - * - * Instead we'll use the get_extension function in MimeClass.inc to discover a valid extension - * for the mimetype in question. - */ - if ($pos === FALSE) { - module_load_include('inc', 'fedora_repository', 'MimeClass'); - $mimeclass = new MimeClass(); - $ext = $mimeclass->get_extension($mimeType); - $suggestedFileName = "$label.$ext"; - } - - header('Content-Disposition: attachment; filename="' . $suggestedFileName . '"'); - } - curl_setopt($ch, CURLOPT_NOBODY, TRUE); $curl_out = curl_exec($ch); + if ($curl_out !== FALSE) { - $info = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); - //dd($info, 'effective URL'); - if ($url !== $info) { //Handle redirect streams (the final URL is not the same as the Fedora URL) + $info = curl_getinfo($ch); + + //Set what headers we can... + if ($mimeType = $info['content_type']) { + header("Content-Type: $mimeType"); + + if ($asAttachment) { + $suggestedFileName = "$label"; + $pos = strpos($suggestedFileName, '.'); + + /* + * Here we used to take an object of, say, type application/pdf with + * label, say, "My Document" and we assemble the output filename + * extension based on the post-slash portion of the mimetype. (If the + * label has a period anywhere in it, we leave it alone.) + * + * This is great for simple mimetypes like application/pdf, text/html, + * image/jpeg, etc., but it's terrible for, say + * application/vnd.oasis.opendocument.text (.odt). + * + * Instead we'll use the get_extension function in MimeClass.inc to + * discover a valid extension for the mimetype in question. + */ + if ($pos === FALSE) { + module_load_include('inc', 'fedora_repository', 'MimeClass'); + $mimeclass = new MimeClass(); + $ext = $mimeclass->get_extension($mimeType); + $suggestedFileName = "$label.$ext"; + } + + header('Content-Disposition: attachment; filename="' . $suggestedFileName . '"'); + } + } + + $effective_url = $info['url']; + //dd($info, 'header/nobody info'); + if ($url !== $effective_url) { //Handle redirect streams (the final URL is not the same as the Fedora URL) //Add the parameters passed to Drupal, leaving out the 'q' $query = array(); @@ -195,7 +207,7 @@ class ObjectHelper { } header('HTTP/1.1 307 Moved Temporarily'); - header('Location: ' . $info . '?' . http_build_query($query)); //Fedora seems to discard the query portion. + header('Location: ' . url($effective_url, array('query' => $query))); } elseif ((isset($user) && $user->uid != 0) || $forceSoap || isset($_SERVER['HTTPS'])) { //If not anonymous, soap is force or we're using HTTPS //Have the webserver mediate the transfer (download and restream) @@ -203,14 +215,25 @@ class ObjectHelper { curl_setopt($ch, CURLOPT_NOBODY, FALSE); curl_setopt($ch, CURLOPT_HTTPGET, TRUE); //CURLOPT_NOBODY sets it to 'HEAD' $toReturn = curl_exec($ch); + + if (($contentSize = self::getBinaryLength($toReturn)) > 0) { + header("Content-Length: $contentSize"); + } + //Done applying headers... + echo $toReturn; } else { + header('HTTP/1.1 307 Moved Temporarily'); header('Location: ' . $url); } } else { - //Curl error... + watchdog('fedora_repository', 'Curl error while trying to get datastream %dsid from Fedora object %dsid. Curl info: !info', array( + '%pid' => $pid, + '%dsid' => $dsID, + '!info' => print_r(curl_getinfo($ch), TRUE), + ), WATCHDOG_WARNING); } } curl_close($ch); @@ -355,7 +378,7 @@ class ObjectHelper { $content = ''; $id = $dataStreamValue->ID; $label = $dataStreamValue->label; - $label = str_replace("_", " ", $label); + //$label = str_replace("_", " ", $label); $label_deslashed = preg_replace('/\//i', '${1}_', $label); // Necessary to handle the case of Datastream labels that contain slashes. Ugh. $mimeType = $dataStreamValue->MIMEType; @@ -364,20 +387,8 @@ class ObjectHelper { 'target' => '_blank', ), )); - $action = url("fedora/repository/object_download/$pid/$id/$label_deslashed"); - $downloadVersion = '
'; - if (user_access(ObjectHelper::$EDIT_FEDORA_METADATA)) { - $versions = $item->get_datastream_history($id); - if (is_array($versions)) { - $downloadVersion = '
'; - $downloadVersion .= ''; - $downloadVersion .= '
'; - } - } + + $downloadVersion = drupal_get_form('fedora_repository_download_datastream_form', $pid, $id, $label_deslashed); return array( array( @@ -407,7 +418,6 @@ class ObjectHelper { function getFormattedDC($item) { global $base_url; $path = drupal_get_path('module', 'fedora_repository'); - module_load_include('inc', 'fedora_repository', 'ConnectionHelper'); $dsid = array_key_exists('QDC', $item->get_datastreams_list_as_array()) ? 'QDC' : 'DC'; $xmlstr = $item->get_datastream_dissemination($dsid); @@ -416,31 +426,68 @@ class ObjectHelper { return ''; } - $simplexml = new SimpleXMLElement($xmlstr); + if (($xsl_path = "$path/xsl/convertQDC.xsl") && + (is_readable($xsl_path)) && + ($xsl = DOMDocument::load($xsl_path)) && //Fails loading XSLT -> FALSE + ($ds = DOMDocument::loadXML($xmlstr))) { + $xslt_opts = array( + 'BASEURL' => $base_url, + 'PATH' => url($path, array('absolute' => TRUE)), + 'baseUrl' => $base_url, //XXX: Deprecated; just here for legacy cases. + 'path' => url($path, array('absolute' => TRUE)), //XXX: Deprecated; just here for legacy cases. + ); + $transform = new XSLTProcessor(); + $transform->importStylesheet($xsl); + $transform->setParameter('', $xslt_opts); + $transformed = $transform->transformToDoc($ds); + return $transformed->saveHTML(); + } + else { + $simplexml = new SimpleXMLElement($xmlstr); - $headers = array( - array( - 'data' => t('Metadata'), - 'colspan' => 2, - ), - ); - $rows = array(); - foreach ($simplexml->getNamespaces(TRUE) as $ns) { - foreach ($simplexml->children($ns) as $child) { - $rows[] = array( - array( - 'data' => $child->getName(), - 'class' => 'dc-tag-name', - ), - array( - 'data' => (string)$child, - 'class' => 'dc-content', - ), - ); + $headers = array( + array( + 'data' => t('Metadata'), + 'colspan' => 2, + ), + ); + $rows = array(); + foreach ($simplexml->getNamespaces(TRUE) as $ns) { + foreach ($simplexml->children($ns) as $child) { + $data = array(); + $rendered_data = ''; + if ($grand_children = $child->children()) { + foreach($grand_children as $grand_child) { + $data[] = $grand_child->getName() . ' = ' . (string)$grand_child; + } + } + else { + $rendered_data = (string)$child; + } + + if ($data) { + $rendered_data = theme('item_list', $data); + } + + if ($rendered_data) { + $rows[] = array( + array( + 'data' => $child->getName(), + 'class' => 'dc-tag-name', + ), + array( + 'data' => $rendered_data, + 'class' => 'dc-content', + ), + ); + } + + + } } - } - return theme('table', $headers, $rows, array('class' => 'dc-table')); + return theme('table', $headers, $rows, array('class' => 'dc-table')); + } } /** @@ -965,21 +1012,33 @@ class ObjectHelper { $breadcrumbs[] = l(t('Home'), ''); } else { - $query_string = 'select $parentObject $title $content from <#ri> - where ( - $title - and $parentObject $content - and ( - $parentObject - or $parentObject - or $parentObject - ) - and $parentObject - ) - minus $content - order by $title desc'; - - if (count($results = self::performItqlQuery($query_string)) > 0 && $level > 0) { + $sparql_query_string = << +PREFIX rels-ext: +SELECT ?parentObject ?title ?content +FROM <#ri> +WHERE { + ?this fedora-model:label ?title ; + ?relationship ?parentObject . + ?parentObject fedora-model:state fedora-model:Active ; + fedora-model:hasModel ?content . + FILTER( + sameTerm(?this, ) && + ( + sameTerm(?relationship, rels-ext:isMemberOfCollection) || + sameTerm(?relationship, rels-ext:isMemberOf) || + sameTerm(?relationship, rels-ext:isPartOf) + ) && + !sameTerm(?content, ) + ) . +} +ORDER BY DESC(?title) +EOQ; + + $results = self::performSparqlQuery($sparql_query_string); + $next_pid = NULL; + + if (count($results) > 0 && $level > 0) { $parent = $results[0]['parentObject']; $this_title = $results[0]['title']; @@ -989,13 +1048,17 @@ class ObjectHelper { $breadcrumbs[] = l($this_title, "fedora/repository/$pid"); - $level--; - $this->getBreadcrumbs($parent, $breadcrumbs); + $next_pid = $parent; } else { - watchdog('fedora_repository', 'Error generating breadcrumbs for %pid. Verify there exists relationships back up to %root. (May also be due to a hierarchy deeper than %max_depth).', array('%pid' => $pid, '%root' => $root, '%max_depth' => $max_depth), WATCHDOG_WARNING); + watchdog('fedora_repository', 'Error generating breadcrumbs for %pid. Verify there exists relationships back up to %root. (May also be due to a hierarchy deeper than %max_depth).', array('%pid' => $pid, '%root' => $root, '%max_depth' => $max_level), WATCHDOG_WARNING); $breadcrumbs[] = '...'; //Add an non-link, as we don't know how to get back to the root. - $this->getBreadcrumbs($root, $breadcrumbs); //And render the last two links and break (on the next pass). + $next_pid = $root; //And cue the last two links to render and break recursion (on the next pass). + } + + if ($next_pid !== NULL) { + $level--; + $this->getBreadcrumbs($next_pid, $breadcrumbs); } } } diff --git a/fedora_repository.module b/fedora_repository.module index e83d91f5..7235aa36 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -377,37 +377,25 @@ function add_stream_form_submit($form, &$form_state) { $form_state['rebuild'] = TRUE; return; } - module_load_include('inc', 'fedora_repository', 'MimeClass'); + module_load_include('inc', 'fedora_repository', 'ObjectHelper'); module_load_include('inc', 'fedora_repository', 'api/fedora_item'); $pathToModule = drupal_get_path('module', 'fedora_repository'); - $file = $form_state['values']['add-stream-file-location']; - $pid = $form_state['values']['pid']; $dsid = $form_state['values']['stream_id']; $dsLabel = $form_state['values']['stream_label'] . substr($file, strrpos($file, '.')); // Add the file extention to the end of the label.; - $file_basename = basename($file); - $file_directory = dirname($file); - $streamUrl = $base_url . '/' . $file_directory . '/' . drupal_urlencode($file_basename); - /* ----------------------------------------------------------------- - * need a better way to get mimetypes - */ - $mimetype = new MimeClass(); - $dformat = $mimetype->getType($file); - $controlGroup = "M"; - if ($dformat == 'text/xml') { - $controlGroup = 'X'; - } try { $item = new Fedora_Item($pid); - $item->add_datastream_from_url($streamUrl, $dsid, $dsLabel, $dformat, $controlGroup); + $item->add_datastream_from_url($form_state['storage']['stream_url'], $dsid, $dsLabel, $form_state['storage']['ds_mimetype'], $form_state['storage']['control_group']); - $object_helper = new ObjectHelper(); - $object_helper->get_and_do_datastream_rules($pid, $dsid, $file); + if ($file = $form_state['values']['add-stream-file-location']) { + $object_helper = new ObjectHelper(); + $object_helper->get_and_do_datastream_rules($pid, $dsid, $file); - file_delete($file); + file_delete($file); + } } catch (exception $e) { drupal_set_message(t('@message', array('@message' => check_plain($e->getMessage()))), 'error'); return; @@ -434,6 +422,7 @@ function add_stream_form(&$form_state, $pid) { * @return type */ function add_stream_form_validate($form, &$form_state) { + module_load_include('inc', 'fedora_repository', 'MimeClass'); if ($form_state['clicked_button']['#value'] == 'OK') { $form_state['rebuild'] = TRUE; return; @@ -444,15 +433,15 @@ function add_stream_form_validate($form, &$form_state) { form_set_error('', t('Data stream ID cannot be more than 64 characters.')); return FALSE; } - if (!(preg_match("/^[a-zA-Z]/", $dsid))) { - form_set_error('', t("Data stream ID (@dsid) has to start with a letter.", array('@dsid' => check_plain($dsid)))); + elseif (!(preg_match("/^[a-zA-Z]/", $dsid))) { + form_set_error('', t("Data stream ID (@dsid) has to start with a letter.", array('@dsid' => $dsid))); return FALSE; } - if (strlen($dsLabel) > 64) { + elseif (strlen($dsLabel) > 64) { form_set_error('', t('Data stream Label cannot be more than 64 characters.')); return FALSE; } - if (strpos($dsLabel, '/')) { + elseif (strpos($dsLabel, '/') !== FALSE) { form_set_error('', t('Data stream Label cannot contain a "/".')); return FALSE; } @@ -461,13 +450,40 @@ function add_stream_form_validate($form, &$form_state) { // 'file_validate_image_resolution' => array('85x85'), // 'file_validate_size' => array(30 * 1024), ); - - $fileObject = file_save_upload('add-stream-file-location', $validators); - -// Move the uploaded file to Drupal's files directory. - file_move($fileObject->filepath, 0, 'FILE_EXISTS_RENAME'); - $form_state['values']['add-stream-file-location'] = $fileObject->filepath; -// TODO: Add error checking here. + + $controlGroup = $form_state['storage']['control_group'] = $form_state['values']['control_group']; + if ((($controlGroup && in_array($controlGroup, array('X', 'M'))) || !$controlGroup) && (($fileObject = file_save_upload('add-stream-file-location', $validators)) !== 0)) { + // Move the uploaded file to Drupal's files directory. + file_move($fileObject->filepath, 0, 'FILE_EXISTS_RENAME'); + $form_state['values']['add-stream-file-location'] = $fileObject->filepath; + + $file_basename = basename($fileObject->filepath); + $file_directory = dirname($fileObject->filepath); + + $form_state['storage']['stream_url'] = url($file_directory . '/' . drupal_urlencode($file_basename), array( + 'absolute' => TRUE, + )); + } + elseif ($controlGroup && in_array($controlGroup, array('M', 'R', 'E')) && ($ref = $form_state['values']['ds_reference'])) { + $form_state['storage']['stream_url'] = $form_state['values']['ds_reference']; + } + else { + form_set_error('', t('No file given when "X" or "M", or no reference given when "M", "R" or "E".')); + } + + $mimeClass = new MimeClass(); + $mimetype = $form_state['storage']['ds_mimetype'] = $mimeClass->getType($form_state['storage']['stream_url']); + + if (!$controlGroup) { + if ($mimetype == 'text/xml') { + $form_state['storage']['control_group'] = 'X'; + } + else { + $form_state['storage']['control_group'] = 'M'; + } + } + + // TODO: Add error checking here. $form_state['rebuild'] = FALSE; } @@ -607,6 +623,42 @@ function fedora_repository_purge_stream_form_submit($form, &$form_state) { $form_state['redirect'] = $base_url . "/fedora/repository/$pid"; } +function fedora_repository_download_datastream_form(&$form_state, $pid, $dsid, $label) { + $form = array( + '#action' => url("fedora/repository/object_download/$pid/$dsid/$label"), + 'submit' => array( + '#type' => 'submit', + '#value' => t('Download'), + ), + ); + + if (user_access(ObjectHelper::$EDIT_FEDORA_METADATA)) { + $item = new Fedora_Item($pid); + $versions = $item->get_datastream_history($dsid); + $version_array = array(); + if (is_array($versions)) { + foreach ($versions as $version) { + $version_array[] = $version->createDate; + } + } + else { + $version_array[] = $versions->createDate; + } + + if (count($version_array) > 1) { + $form['#attributes'] = array( + 'onsubmit' => 'this.action="' . $form['#action'] . '/" + this.version.value;' + ); + $form['version'] = array( + '#type' => 'select', + '#options' => array_combine($version_array, $version_array), + ); + } + } + + return $form; +} + /** * fedora repository replace stream * @param type $pid @@ -646,27 +698,31 @@ function fedora_repository_replace_stream_form(&$form_state, $pid, $dsId, $dsLab * @return type */ function fedora_repository_replace_stream_form_validate($form, &$form_state) { -// If a file was uploaded, process it. + // If a file was uploaded, process it. if (isset($_FILES['files']) && is_uploaded_file($_FILES['files']['tmp_name']['file'])) { -// attempt to save the uploaded file + // attempt to save the uploaded file $file = file_save_upload('file', array(), file_directory_path()); -// set error is file was not uploaded + // set error is file was not uploaded if (!$file) { form_set_error('file', 'Error uploading file.'); return; } - - $doc = new DOMDocument(); - module_load_include('inc', 'Fedora_Repository', 'MimeClass'); + + /* ----------------------------------------------------------------- + * TODO: need a better way to get mimetypes + */ + module_load_include('inc', 'fedora_repository', 'MimeClass'); $mime = new MimeClass(); - if ($mime->getType($file->filepath) == 'text/xml' && !$doc->load($file->filepath)) { + $mimetype = $form_state['storage']['mime_type'] = $mime->getType($file->filepath); + + if ($mimetype == 'text/xml' && !DOMDocument::load($file->filepath)) { form_set_error('file', 'Invalid XML format.'); return; } -// set files to form_state, to process when form is submitted + // set files to form_state, to process when form is submitted $form_state['values']['file'] = $file; } } @@ -678,45 +734,28 @@ function fedora_repository_replace_stream_form_validate($form, &$form_state) { * @param array $form_state */ function fedora_repository_replace_stream_form_submit($form, &$form_state) { - global $base_url; $file = $form_state['values']['file']; + $pid = $form_state['values']['pid']; $dsid = $form_state['values']['dsId']; $dsLabel = $form_state['values']['dsLabel']; -// Remove the original file extension from the label and add the new one - $indexOfDot = strrpos($dsLabel, '.'); //use strrpos to get the last dot - if ($indexOfDot !== FALSE) { - $dsLabel = substr($dsLabel, 0, $indexOfDot); - $dsLabel .= substr($file->filename, strrpos($file->filename, '.')); // Add the file extention to the end of the label.; + + $streamUrl = ($file !== NULL) ? + $file->filepath: + url($form_state['values']['reference'], array('absolute' => TRUE)); + + // Remove the original file extension from the label and add the new one + // use strrpos to get the last dot + if (($indexOfDot = strrpos($dsLabel, '.')) !== FALSE) { + $dsLabel = substr($dsLabel, 0, $indexOfDot) . + substr($streamUrl, strrpos($streamUrl, '.')); // Add the file extention to the end of the label. } - module_load_include('inc', 'Fedora_Repository', 'MimeClass'); - module_load_include('inc', 'fedora_repository', 'api/fedora_item'); - $file_basename = basename($file->filepath); - $file_directory = dirname($file->filepath); - $streamUrl = $base_url . '/' . $file_directory . '/' . urlencode($file_basename); - - /* ----------------------------------------------------------------- - * TODO: need a better way to get mimetypes - */ - $mimetype = new MimeClass(); - $dformat = $mimetype->getType($file->filepath); + $dformat = $form_state['storage']['mime_type']; + module_load_include('inc', 'fedora_repository', 'api/fedora_item'); $item = new Fedora_Item($pid); - $info = $item->get_datastream_info($dsid); - - if($info->datastream->controlGroup == 'M') { - $item->modify_datastream_by_reference($streamUrl, $dsid, $dsLabel, $dformat); - } elseif ($info->datastream->controlGroup == 'X') { - if($dformat == 'text/xml') { - $item->modify_datastream_by_value(file_get_contents($file->filepath), $dsid, $dsLabel, $dformat); - } - else { - drupal_set_message('File must be of mimetype text/xml in order to replace inline XML datastream.', 'error'); - } - } else { - drupal_set_message('Cannot replace Redirect or Managed Datastream.', 'error'); - } + $item->modify_datastream($streamUrl, $dsid, $dsLabel, $dformat); $form_state['redirect'] = 'fedora/repository/' . $pid; } @@ -912,17 +951,97 @@ function makeObject($pid, $dsID) { } /** - * Sends an ITQL query to the Fedora Resource index (can only communicate with Kowari or mulgara) - * Reads the pid and datastream id as url parameters. Queries the collection object for the query - * if there is no query datastream falls back to the query shipped with the module. + * Implementation of hook_islandora_tabs(). + * + * @param $content_models array + * An array of ContentModel objects to which the current Fedora Object + * subscribes. + * @param $pid string + * A string containing the Fedora PID of the current Fedora Object. + * @param $page_number integer + * An integer for which page we should start on in the loaded object. + * @return array + * An array containing a tabset (an array of tabpages), renderable with + * drupal_render(). + */ +function fedora_repository_islandora_tabs($content_models, $pid, $page_number) { + $cmodels_tabs = array(); + + foreach ($content_models as $content_model) { + $content_model_fieldset = $content_model->displayExtraFieldset($pid, $page_number); + + // Each content model may return either a tabpage array or plain HTML. If + // it is HTML, stick it in a tabpage. + if (is_array($content_model_fieldset)) { + $cmodels_tabs = array_merge($cmodels_tabs, $content_model_fieldset); + } + else { + $cmodels_tabs[$content_model->pid] = array( + '#type' => 'tabpage', + '#title' => $content_model->name, + '#content' => $content_model_fieldset, + ); + } + } + + // Add a 'manage object' tab for all objects, where detailed list of content is shown. + // XXX: Perhaps this should be extracted into its own object? + module_load_include('inc', 'fedora_repository', 'plugins/FedoraObjectDetailedContent'); + $obj = new FedoraObjectDetailedContent($pid); + + //can disable showing the object details tab in admin UI + if (variable_get('fedora_repository_show_object_details_tab', TRUE)) { + $object_details = $obj->showFieldSets(); + $cmodel_tabs = array_merge($cmodels_tabs, $object_details); + } + + return array_merge($cmodels_tabs, $object_details); +} + +/** + * Implementation of hook_islandora_tabs_alter(). + * + * @param &$tabs array + * The array of tabs/tabset to alter. + * @param $params array + * An associative array containing the parameters with which the original + * hook was called. + * @see fedora_repository_get_items() + */ +function fedora_repository_islandora_tabs_alter(&$tabs, $params) { + //Deselect all other tabs if the fedora_object_details tab is supposed + // to be selected. + $object_details_key = 'fedora_object_details'; + if ($tabs[$object_details_key]['#selected']) { + foreach (element_children($tabs) as $key) { + if ($key != $object_details_key) { + $tabs[$key]['#selected'] = FALSE; + } + } + } +} + +/** + * Menu callback for "fedora/repository". + * + * If user is allow, and we are given a PID and a sensical DSID, return the + * datastream via the makeObject() function; otherwise, call out to the PIDs' + * ContentModels and all Drupal modules for Islandora tabs. * - * @global type $user - * @param type $pid - * @param type $dsId - * @param type $collection - * @param type $page_number - * @param type $limit - * @return type + * @global $user stdObject + * @param $pid string + * An optional string containing the PID of an object. (defaults to islandora:root) + * @param $dsId string + * An optional string containing the dsid of an object. ("-" will be ignored + * to allow later parameters without including one). + * @param $collection string + * The collection name... Deprecated. + * @param $page_number string/integer(?) + * A page number to start on... Seems to be going towards deprecation? + * @param $limit string/integer(?) + * Used to limit the number of results returned? Deprecated? + * @return string + * A string containing markup for the rendered tabs. */ function fedora_repository_get_items($pid = NULL, $dsId = NULL, $collection = NULL, $page_number = NULL, $limit = NULL) { module_load_include('inc', 'fedora_repository', 'ObjectHelper'); @@ -944,7 +1063,7 @@ function fedora_repository_get_items($pid = NULL, $dsId = NULL, $collection = NU $pid = variable_get('fedora_repository_pid', 'islandora:root'); } - $item = new fedora_item($pid); + $item = new Fedora_Item($pid); if (!$item->exists()) { drupal_not_found(); exit(); @@ -983,57 +1102,30 @@ function fedora_repository_get_items($pid = NULL, $dsId = NULL, $collection = NU return makeObject($pid, $dsId); } - $content = '
'; - - module_load_include('inc', 'fedora_repository', 'CollectionClass'); - $collectionClass = new CollectionClass(); - module_load_include('inc', 'fedora_repository', 'ContentModel'); - module_load_include('inc', 'fedora_repository', 'plugins/FedoraObjectDetailedContent'); $breadcrumbs = array(); $objectHelper->getBreadcrumbs($pid, $breadcrumbs); drupal_set_breadcrumb(array_reverse($breadcrumbs)); - $offset = $limit * $page_number; $content_models = $objectHelper->get_content_models_list($pid); -// Each content model may return either a tabset array or plain HTML. If it's HTML, stick it in a tab. - $cmodels_tabs = array( - '#type' => 'tabset', + + //Get the tabs from all modules... + $hook_tabs = module_invoke_all('islandora_tabs', $content_models, $pid, $page_number); + + $cmodels_tabs = array( + '#type' => 'tabset', ); - foreach ($content_models as $content_model) { - $content_model_fieldset = $content_model->displayExtraFieldset($pid, $page_number); - if (is_array($content_model_fieldset)) { - $cmodels_tabs = array_merge($cmodels_tabs, $content_model_fieldset); - } - else { - $cmodels_tabs[$content_model->pid] = array( - '#type' => 'tabpage', - '#title' => $content_model->name, - '#content' => $content_model_fieldset, - ); - } - } + $cmodels_tabs += $hook_tabs; -// Add a 'manage object' tab for all objects, where detailed list of content is shown. - $obj = new FedoraObjectDetailedContent($pid); + //Assemble parameters, to pass during alter + $params = array( + 'content_models' => $content_models, + 'pid' => $pid, + 'page' => $page_number, + ); + + //Allow returned tabs to be altered, before return. + drupal_alter('islandora_tabs', $cmodels_tabs, $params); - //can disable showing the object details tab in admin UI - if (variable_get('fedora_repository_show_object_details_tab', TRUE)) { - $object_details = $obj->showFieldSets(); - if ($object_details['fedora_object_details']['#selected'] == TRUE) { - foreach ($cmodels_tabs as &$cmodel_tab) { - if (is_array($cmodel_tab)) { - $cmodel_tab['#selected'] = FALSE; - } - } - } - } - else { - $object_details = array(); - } - - $hook_tabs = module_invoke_all('islandora_tabs', $content_models, $pid); - $cmodels_tabs = array_merge($cmodels_tabs, $object_details, $hook_tabs); - return tabs_render($cmodels_tabs); } @@ -1059,7 +1151,6 @@ function fedora_repository_urlencode_string($str) { * @return type */ function fedora_object_as_attachment($pid, $dsId, $label=NULL, $version=NULL) { - global $user; module_load_include('inc', 'fedora_repository', 'ObjectHelper'); if ($pid == NULL || $dsId == NULL) { @@ -1068,7 +1159,7 @@ function fedora_object_as_attachment($pid, $dsId, $label=NULL, $version=NULL) { } $objectHelper = new ObjectHelper(); - $objectHelper->makeObject($pid, $dsId, 1, $label, FALSE, $version); + $objectHelper->makeObject($pid, $dsId, TRUE, $label, FALSE, $version); } /** @@ -2273,9 +2364,6 @@ function theme_fedora_repository_solution_packs_list($solution_packs) { $header = array(); $rows = array(); - - - drupal_add_css(drupal_get_path('module', 'update') . '/update.css'); return $output; } diff --git a/formClass.inc b/formClass.inc index 713f1fcb..a5f9bef6 100644 --- a/formClass.inc +++ b/formClass.inc @@ -331,6 +331,13 @@ class formClass { '#options' => array(ObjectHelper::$DISPLAY_ALWAYS => t('Always'), ObjectHelper::$DISPLAY_NEVER => t('Never'), ObjectHelper::$DISPLAY_NO_MODEL_OUTPUT => t('Only if no Content Model display output.')), '#description' => t('Determines when to display the list of objects when viewing a collection page.'), ); + + $form['advanced']['fedora_control_group_control_during_ingest'] = array( + '#type' => 'checkbox', + '#title' => t('Allow control groups select in datastream ingest'), + '#description' => t('Whether or not we should allow the user to select which control group to ingest a stream as, or to follow the old paradigm--to add stream IDed as XML as inline, and everything else as managed.'), + '#default_value' => variable_get('fedora_control_group_control_during_ingest', FALSE), + ); //Export functionality $form['advanced']['module']['export_area'] = array( @@ -656,17 +663,21 @@ class formClass { } } - $form['add_datastream_label'] = array( - '#value' => t('

Add Datastream:

'), - '#weight' => -10, + $form['fieldset'] = array( + '#type' => 'fieldset', + '#title' => t('Add datastream'), ); + //$form['add_datastream_label'] = array( + // '#value' => t('

Add Datastream:

'), + // '#weight' => -10, + //); - $form['pid'] = array( + $form['fieldset']['pid'] = array( '#type' => 'hidden', '#value' => "$pid" ); - $form['stream_label'] = array( + $form['fieldset']['stream_label'] = array( '#title' => 'Datastream Label', '#required' => 'TRUE', '#description' => t('A Human readable label'), @@ -674,35 +685,41 @@ class formClass { ); $form['#attributes']['enctype'] = 'multipart/form-data'; - $form['add-stream-file-location'] = array( + $form['fieldset']['add-stream-file-location'] = array( '#type' => 'file', '#title' => t('Upload Document'), '#size' => 48, // '#required'=>'TRUE', - '#description' => t('The file to upload.') + '#description' => t('The file to upload. (Only for Managed and Inline)') ); + + if (variable_get('fedora_control_group_control_during_ingest', FALSE)) { + $form['fieldset']['ds_reference'] = array( + '#type' => 'textfield', + '#title' => t('Datastream reference'), + '#size' => 48, + '#description' => t('A URL reference to resolve for the contents of the datastream. (Required for External and Redirect, but will still work for Managed and Inline.)'), + ); + } + $form['#redirect'] = "fedora/repository/$pid/"; - $form['submit'] = array( + $form['fieldset']['submit'] = array( '#type' => 'submit', '#value' => t('Add Datastream') ); if (!empty($unused_dsids)) { - $dsidsForForm = array(); - foreach ($unused_dsids as $dsid) { - $dsidsForForm[$dsid] = $dsid; - } - $form['stream_id'] = array( + $form['fieldset']['stream_id'] = array( '#type' => 'select', '#title' => t('Datastream ID'), '#default_value' => variable_get('feed_item_length', 'teaser'), - '#weight' => '-1', + '#weight' => -1, '#description' => t('Datastream IDs defined by the content model.'), + '#options' => array_combine($unused_dsids, $unused_dsids), ); - $form['stream_id']['#options'] = array_combine($unused_dsids, $unused_dsids); } else { - $form['stream_id'] = array( + $form['fieldset']['stream_id'] = array( '#title' => 'Datastream ID', '#required' => 'TRUE', '#description' => t('An ID for this stream that is unique to this object. Must start with a letter and contain only alphanumeric characters and dashes and underscores.'), @@ -710,6 +727,21 @@ class formClass { '#weight' => -1, ); } + + if (variable_get('fedora_control_group_control_during_ingest', FALSE)) { + $form['fieldset']['control_group'] = array( + '#type' => 'select', + '#title' => t('Control group'), + '#options' => array( + 'X' => t('Inline XML'), + 'M' => t('Managed datastream'), + 'E' => t('Externally Referenced/managed datastream'), + 'R' => t('Redirect datastream'), + ), + '#description' => t('The manner in which the datastream will be stored. "Inline XML" must be XML and will be placed directly into the FOXML for the object. "Managed" datastreams are made to live on the filesystem as discrete files in the Fedora data directory. Both "Redirect" and "External" streams are URL references; the difference being the redirect stream instruct clients to perform an HTTP redirect, such that the data does not pass though Fedora (useful for streaming). External streams are mediated (by which I mean loaded and streamed from) the Fedora server.'), + '#weight' => 0, + ); + } return $form; } @@ -836,12 +868,33 @@ class formClass { $form = array(); $form['#attributes']['enctype'] = 'multipart/form-data'; - $form['file'] = array( - '#type' => 'file', - '#title' => t('Upload Document'), - '#description' => t('The file to upload.') - ); - + + module_load_include('inc', 'fedora_repository', 'api/fedora_item'); + $item = new Fedora_Item($pid); + $info = $item->get_datastream_info($dsId); + $control_group = $info->datastream->controlGroup; + if (in_array($control_group, array('M', 'X'))) { + $form['file'] = array( + '#type' => 'file', + '#title' => t('Upload Document'), + '#description' => t('A file with which to replace the contents of this datastream.'), + ); + } + if ($control_group != 'X') { + $form['reference'] = array( + '#type' => 'textfield', + '#title' => t('Reference to object'), + '#description' => t('A URL the datastream will be updated to reference.'), + ); + } + if ($control_group == 'M') { + $form['note'] = array( + '#type' => 'item', + '#title' => t('NOTE'), + '#value' => t('If both a file and a reference are given, the file will be given preference.'), + ); + } + $form['pid'] = array( '#type' => 'value', '#value' => $pid, diff --git a/plugins/tagging_form.inc b/plugins/tagging_form.inc index f00274d4..9b7c4658 100644 --- a/plugins/tagging_form.inc +++ b/plugins/tagging_form.inc @@ -61,15 +61,16 @@ function fedora_repository_image_tagging_form($form_state, $pid) { $tagset = new TagSet($obj); $tags = array(); foreach ($tagset->tags as $tag) { - $form_tag =& $form['tags-wrapper']['tags'][$tag['name']] = array( + $form['tags-wrapper']['tags'][$tag['name']] = array( '#prefix' => '
  • ', '#suffix' => '
  • ', ); + $form_tag =& $form['tags-wrapper']['tags'][$tag['name']]; $tag_title_text = t('Added by @creator.', array( '@creator' => $tag['creator'], )); - $tag_mnpl_search_path = "fedora/repository/mnpl_advanced_search/tag:{$tag['name']}" + $tag_mnpl_search_path = "fedora/repository/mnpl_advanced_search/tag:{$tag['name']}"; $form_tag['tag'] = array( '#value' => l($tag['name'], $tag_mnpl_search_path, array('attributes' => array( 'title' => $tag_title_text diff --git a/xsl/convertQDC.xsl b/xsl/convertQDC.xsl deleted file mode 100644 index 5d881e35..00000000 --- a/xsl/convertQDC.xsl +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - -
    - - - - - - - - - - -

    MetaData

    - -
    - = -
    -
    -
    - -
    - - -
    \ No newline at end of file diff --git a/xsl/convertQDC.xsl.deprecated b/xsl/convertQDC.xsl.deprecated new file mode 100644 index 00000000..724f7c70 --- /dev/null +++ b/xsl/convertQDC.xsl.deprecated @@ -0,0 +1,34 @@ + + + + + + + + +
    + + + + + + + + + + + + + + + + + +

    MetaData

    + +
    +
    +
    +
    +
    +