From 48c155153302b4c19a2eaeee019230cfeabf3f4e Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 12 Jul 2011 14:14:25 -0300 Subject: [PATCH 01/19] Fix Headers for FlowPlayer FlowPlayer requires the "Content-Length" header to be returned in order to work properly, but it wasn't getting returned in the header when a user was not logged in. A slight change to the semantics, and opening up of the getDatastream API-M method via XACML seems to work. --- ObjectHelper.inc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index e866f62f..d054f233 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -107,14 +107,13 @@ 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)) { From 2d9c55fc5d30bc8e4165adeb0d9745a79a8621a3 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Thu, 26 Apr 2012 16:05:48 -0300 Subject: [PATCH 02/19] Make a little closed to convertQDC.xsl --- ObjectHelper.inc | 39 +++++++++++++++++++++++++++++---------- plugins/tagging_form.inc | 3 ++- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index d054f233..975a3344 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -426,16 +426,35 @@ class ObjectHelper { $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', - ), - ); + $data = array(); + $rendered_data = ''; + if ($grand_children = $child->children()) { + foreach($grand_children as $grand_child) { + $data[] = $grand_child->tagName() . ' = ' . (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', + ), + ); + } + + } } diff --git a/plugins/tagging_form.inc b/plugins/tagging_form.inc index f00274d4..ae3bba92 100644 --- a/plugins/tagging_form.inc +++ b/plugins/tagging_form.inc @@ -61,10 +61,11 @@ 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'], From fe7628559f0099b709f336ce7a4578b820b0af07 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 24 Apr 2012 14:19:47 -0300 Subject: [PATCH 03/19] Use wrapping modify_datastream wrapper in replace datastream callback. --- fedora_repository.module | 45 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/fedora_repository.module b/fedora_repository.module index e83d91f5..208e028e 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -646,27 +646,27 @@ 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'); + + module_load_include('inc', 'fedora_repository', 'MimeClass'); $mime = new MimeClass(); - if ($mime->getType($file->filepath) == 'text/xml' && !$doc->load($file->filepath)) { + + if ($mime->getType($file->filepath) == '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; } } @@ -683,39 +683,32 @@ function fedora_repository_replace_stream_form_submit($form, &$form_state) { $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 + + // 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.; } - 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); + $streamUrl = url($file->filepath, array( + 'absolute' => TRUE, + )); /* ----------------------------------------------------------------- * TODO: need a better way to get mimetypes */ + module_load_include('inc', 'fedora_repository', 'MimeClass'); $mimetype = new MimeClass(); $dformat = $mimetype->getType($file->filepath); + 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'); - } + + if(in_array($info->datastream->controlGroup, array('M', 'X'))) { + $item->modify_datastream($streamUrl, $dsid, $dsLabel, $dformat); } else { - drupal_set_message('Cannot replace Redirect or Managed Datastream.', 'error'); + drupal_set_message(t('Cannot replace Redirect or Managed Datastream.'), 'error'); } $form_state['redirect'] = 'fedora/repository/' . $pid; From 842b8b5a311c50912f26bf5dffda24086ffa43a9 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Wed, 25 Apr 2012 09:22:14 -0300 Subject: [PATCH 04/19] Get the extension without exploding. --- MimeClass.inc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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) From c3ccdec4b671873c9f37cd7a3cbe504195d10970 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Wed, 25 Apr 2012 10:05:45 -0300 Subject: [PATCH 05/19] Allow the addition of Redirect and External datastreams. --- ObjectHelper.inc | 14 ++++--- fedora_repository.module | 83 +++++++++++++++++++++------------------- formClass.inc | 83 +++++++++++++++++++++++++++++----------- 3 files changed, 113 insertions(+), 67 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index 975a3344..8af4d06c 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -72,7 +72,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 +90,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) { @@ -122,8 +120,14 @@ class ObjectHelper { $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)"; @@ -183,7 +187,6 @@ class ObjectHelper { $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) //Add the parameters passed to Drupal, leaving out the 'q' @@ -194,7 +197,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($info, 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) @@ -210,6 +213,7 @@ class ObjectHelper { } else { //Curl error... + watchdog('fedora_repository', 'Curl error. Info: @info', array('@info' => print_r(curl_getinfo($ch), TRUE)), WATCHDOG_WARNING); } } curl_close($ch); diff --git a/fedora_repository.module b/fedora_repository.module index 208e028e..28dc4e8e 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['values']['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; } @@ -462,12 +451,30 @@ function add_stream_form_validate($form, &$form_state) { // '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. + $mimetype = new MimeClass(); + $controlGroup = $form_state['values']['control_group']; + if (in_array($controlGroup, array('X', 'M')) && ($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; + $form_state['storage']['ds_mimetype'] = $mimetype->getType($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 (in_array($controlGroup, array('M', 'R', 'E')) && ($ref = $form_state['values']['ds_reference'])) { + $form_state['storage']['ds_mimetype'] = $mimetype->getType($ref); + $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".')); + } + + // TODO: Add error checking here. $form_state['rebuild'] = FALSE; } @@ -680,6 +687,11 @@ function fedora_repository_replace_stream_form_validate($form, &$form_state) { function fedora_repository_replace_stream_form_submit($form, &$form_state) { global $base_url; $file = $form_state['values']['file']; + + if ($file !== NULL) { + $file = $form_state['values']['reference']; + } + $pid = $form_state['values']['pid']; $dsid = $form_state['values']['dsId']; $dsLabel = $form_state['values']['dsLabel']; @@ -702,14 +714,9 @@ function fedora_repository_replace_stream_form_submit($form, &$form_state) { $mimetype = new MimeClass(); $dformat = $mimetype->getType($file->filepath); - module_load_include('inc', 'fedora_repository', 'api/fedora_item'); $item = new Fedora_Item($pid); - if(in_array($info->datastream->controlGroup, array('M', 'X'))) { - $item->modify_datastream($streamUrl, $dsid, $dsLabel, $dformat); - } else { - drupal_set_message(t('Cannot replace Redirect or Managed Datastream.'), 'error'); - } + $item->modify_datastream($streamUrl, $dsid, $dsLabel, $dformat); $form_state['redirect'] = 'fedora/repository/' . $pid; } @@ -1052,7 +1059,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) { @@ -1061,7 +1067,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); } /** @@ -2266,9 +2272,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..db90798c 100644 --- a/formClass.inc +++ b/formClass.inc @@ -656,17 +656,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 +678,37 @@ 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)') + ); + $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 +716,18 @@ class formClass { '#weight' => -1, ); } + $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 +854,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, From b609a8fd5c19c1c525272d9514e4cd32a3facf83 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Wed, 25 Apr 2012 11:04:13 -0300 Subject: [PATCH 06/19] Make control group selection optional. --- fedora_repository.module | 62 +++++++++++++++++++++------------------- formClass.inc | 50 ++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 47 deletions(-) diff --git a/fedora_repository.module b/fedora_repository.module index 28dc4e8e..f5e8602e 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -388,7 +388,7 @@ function add_stream_form_submit($form, &$form_state) { try { $item = new Fedora_Item($pid); - $item->add_datastream_from_url($form_state['storage']['stream_url'], $dsid, $dsLabel, $form_state['storage']['ds_mimetype'], $form_state['values']['control_group']); + $item->add_datastream_from_url($form_state['storage']['stream_url'], $dsid, $dsLabel, $form_state['storage']['ds_mimetype'], $form_state['storage']['control_group']); if ($file = $form_state['values']['add-stream-file-location']) { $object_helper = new ObjectHelper(); @@ -450,14 +450,12 @@ function add_stream_form_validate($form, &$form_state) { // 'file_validate_image_resolution' => array('85x85'), // 'file_validate_size' => array(30 * 1024), ); - - $mimetype = new MimeClass(); - $controlGroup = $form_state['values']['control_group']; - if (in_array($controlGroup, array('X', 'M')) && ($fileObject = file_save_upload('add-stream-file-location', $validators)) !== 0) { + + $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; - $form_state['storage']['ds_mimetype'] = $mimetype->getType($fileObject->filepath); $file_basename = basename($fileObject->filepath); $file_directory = dirname($fileObject->filepath); @@ -466,14 +464,25 @@ function add_stream_form_validate($form, &$form_state) { 'absolute' => TRUE, )); } - elseif (in_array($controlGroup, array('M', 'R', 'E')) && ($ref = $form_state['values']['ds_reference'])) { - $form_state['storage']['ds_mimetype'] = $mimetype->getType($ref); + 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; } @@ -665,10 +674,14 @@ function fedora_repository_replace_stream_form_validate($form, &$form_state) { return; } + /* ----------------------------------------------------------------- + * TODO: need a better way to get mimetypes + */ module_load_include('inc', 'fedora_repository', 'MimeClass'); $mime = new MimeClass(); + $mimetype = $form_state['storage']['mime_type'] = $mime->getType($file->filepath); - if ($mime->getType($file->filepath) == 'text/xml' && !DOMDocument::load($file->filepath)) { + if ($mimetype == 'text/xml' && !DOMDocument::load($file->filepath)) { form_set_error('file', 'Invalid XML format.'); return; } @@ -685,37 +698,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']; - - if ($file !== NULL) { - $file = $form_state['values']['reference']; - } - + $pid = $form_state['values']['pid']; $dsid = $form_state['values']['dsId']; $dsLabel = $form_state['values']['dsLabel']; + $streamUrl = ($file !== NULL) ? + url($file->filepath, array('absolute' => TRUE)): + url($form_state['values']['reference'], array('absolute' => TRUE)); + // 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.; + // 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. } - $streamUrl = url($file->filepath, array( - 'absolute' => TRUE, - )); + - /* ----------------------------------------------------------------- - * TODO: need a better way to get mimetypes - */ - module_load_include('inc', 'fedora_repository', 'MimeClass'); - $mimetype = new MimeClass(); - $dformat = $mimetype->getType($file->filepath); + $dformat = $form_state['storage']['mime_type']; $item = new Fedora_Item($pid); - $item->modify_datastream($streamUrl, $dsid, $dsLabel, $dformat); $form_state['redirect'] = 'fedora/repository/' . $pid; diff --git a/formClass.inc b/formClass.inc index db90798c..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( @@ -685,12 +692,16 @@ class formClass { // '#required'=>'TRUE', '#description' => t('The file to upload. (Only for Managed and Inline)') ); - $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.)'), - ); + + 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['fieldset']['submit'] = array( '#type' => 'submit', @@ -716,18 +727,21 @@ class formClass { '#weight' => -1, ); } - $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, - ); + + 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; } From c76891ff256f574aad6517c0ac2762affd985ffb Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Thu, 26 Apr 2012 09:48:03 -0300 Subject: [PATCH 07/19] Use Sparql query for breadcrumbs. --- ObjectHelper.inc | 52 +++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index 8af4d06c..54b384be 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -987,21 +987,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']; @@ -1011,13 +1023,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); $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); } } } From 948bba982726d4aad154db8ae98dcf0f8e40a26b Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Thu, 26 Apr 2012 10:03:45 -0300 Subject: [PATCH 08/19] Generate the download form. ... As opposed to spitting out markup for it directly. --- ObjectHelper.inc | 20 ++++---------------- fedora_repository.module | 36 ++++++++++++++++++++++++++++++++++++ plugins/tagging_form.inc | 2 +- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index 54b384be..fb28a9ef 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -358,7 +358,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; @@ -367,20 +367,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( @@ -1026,7 +1014,7 @@ EOQ; $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. $next_pid = $root; //And cue the last two links to render and break recursion (on the next pass). } diff --git a/fedora_repository.module b/fedora_repository.module index f5e8602e..5b6052b1 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -623,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 diff --git a/plugins/tagging_form.inc b/plugins/tagging_form.inc index ae3bba92..9b7c4658 100644 --- a/plugins/tagging_form.inc +++ b/plugins/tagging_form.inc @@ -70,7 +70,7 @@ function fedora_repository_image_tagging_form($form_state, $pid) { $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 From 373c390a8761b86508286edb747f120bfa9eefa5 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 27 Apr 2012 10:12:21 -0300 Subject: [PATCH 09/19] Try to use covertQDC.xsl before using the Drupal's table generating business. --- ObjectHelper.inc | 87 ++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index fb28a9ef..a90b3544 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -407,50 +407,59 @@ class ObjectHelper { return ''; } - $simplexml = new SimpleXMLElement($xmlstr); + if (($xsl_path = "$path/xsl/convertQDC.xsl") && + ($xsl = DOMDocument::load($xsl_path)) && + ($ds = DOMDocument::loadXML($xmlstr))) { + $transform = new XSLTProcessor(); + $transform->importStylesheet($xsl); + return $transform->transformToXML($ds); + } + 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) { - $data = array(); - $rendered_data = ''; - if ($grand_children = $child->children()) { - foreach($grand_children as $grand_child) { - $data[] = $grand_child->tagName() . ' = ' . (string)$grand_child; + $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', + ), + ); + } + + } - 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')); + } } /** From d44aca62d12b810ba5a3c570d8ce982174cd0a47 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 27 Apr 2012 10:38:21 -0300 Subject: [PATCH 10/19] Format XSLT and pass parameters. --- ObjectHelper.inc | 10 +++++++- xsl/convertQDC.xsl | 62 +++++++++++++++++++++++----------------------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index a90b3544..19c2cfc7 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -410,9 +410,17 @@ class ObjectHelper { if (($xsl_path = "$path/xsl/convertQDC.xsl") && ($xsl = DOMDocument::load($xsl_path)) && ($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); - return $transform->transformToXML($ds); + $transform->setParameter('', $xslt_opts); + $transformed = $transform->transformToDoc($ds); + return $transformed->saveHTML(); } else { $simplexml = new SimpleXMLElement($xmlstr); diff --git a/xsl/convertQDC.xsl b/xsl/convertQDC.xsl index 5d881e35..62edd12e 100644 --- a/xsl/convertQDC.xsl +++ b/xsl/convertQDC.xsl @@ -1,33 +1,33 @@ - - - - - - - - -
    - - - - - - - - - - -

    MetaData

    - -
    - = -
    -
    -
    - -
    - - -
    \ No newline at end of file + + + + + +
    + + + + + + + + + + + + + + + + + +

    MetaData

    + +
    +
    +
    +
    +
    + From 1068dbde0afe3b7f171cb07b22f9639cb1fced39 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 27 Apr 2012 10:45:56 -0300 Subject: [PATCH 11/19] Add comments and rename XSLT so it is not used by default... The XSLT will still be used if it is present, though. --- ObjectHelper.inc | 3 +-- xsl/{convertQDC.xsl => convertQDC.xsl.deprecated} | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) rename xsl/{convertQDC.xsl => convertQDC.xsl.deprecated} (85%) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index 19c2cfc7..bf1d1100 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -398,7 +398,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); @@ -408,7 +407,7 @@ class ObjectHelper { } if (($xsl_path = "$path/xsl/convertQDC.xsl") && - ($xsl = DOMDocument::load($xsl_path)) && + ($xsl = DOMDocument::load($xsl_path)) && //Fails loading XSLT -> FALSE ($ds = DOMDocument::loadXML($xmlstr))) { $xslt_opts = array( 'BASEURL' => $base_url, diff --git a/xsl/convertQDC.xsl b/xsl/convertQDC.xsl.deprecated similarity index 85% rename from xsl/convertQDC.xsl rename to xsl/convertQDC.xsl.deprecated index 62edd12e..724f7c70 100644 --- a/xsl/convertQDC.xsl +++ b/xsl/convertQDC.xsl.deprecated @@ -1,4 +1,5 @@ + From 0d6c34e10f10920c5a2c9dafe266573e1b444ca0 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 30 Apr 2012 18:08:46 -0300 Subject: [PATCH 12/19] Avoid warning/error when file does not exist. --- ObjectHelper.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ObjectHelper.inc b/ObjectHelper.inc index bf1d1100..9b7753f7 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -2,7 +2,7 @@ /** - * @file + * @file * Object Helper Class */ @@ -407,6 +407,7 @@ class ObjectHelper { } 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( From ee4427910b6fe44e8540c3302f968b3feab686b1 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 30 Apr 2012 18:19:57 -0300 Subject: [PATCH 13/19] Extract Drupal collection view assembly into separate function. Hurray for enabling code reuse! --- CollectionClass.inc | 118 ++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 42 deletions(-) diff --git a/CollectionClass.inc b/CollectionClass.inc index 5882a460..93733259 100644 --- a/CollectionClass.inc +++ b/CollectionClass.inc @@ -672,6 +672,75 @@ 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); + + $results = array(); + foreach (array_slice($sparql_results, $per_page * $pager_page, $per_page) as $result) { + $title = $result['title']; + $obj_path = "fedora/repository/{$result['object']}"; + $tn_path = ($result['thumbnail'] ? + "fedora/repository/{$result['thumbnail']}": + "$obj_path/TN"); + $thumbnail = theme('image', $tn_path, $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, + )); + + 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 +772,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) { From c01495947a0f8accea96f4d2c3361b6711d6052f Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Mon, 30 Apr 2012 18:20:50 -0300 Subject: [PATCH 14/19] Add the page parameter to the islandora_tabs hook call. ... Facilitates implementation of equivalent functionality, where the object was instantiated with the PID, and then the page was passed to the method declared in your ISLANDORACM stream. --- CollectionClass.inc | 8 +++----- ObjectHelper.inc | 2 -- fedora_repository.module | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/CollectionClass.inc b/CollectionClass.inc index 93733259..18d5a107 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) { diff --git a/ObjectHelper.inc b/ObjectHelper.inc index 9b7753f7..eead665e 100644 --- a/ObjectHelper.inc +++ b/ObjectHelper.inc @@ -32,8 +32,6 @@ 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(); } /** diff --git a/fedora_repository.module b/fedora_repository.module index 5b6052b1..a9209294 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -1071,7 +1071,7 @@ function fedora_repository_get_items($pid = NULL, $dsId = NULL, $collection = NU $object_details = array(); } - $hook_tabs = module_invoke_all('islandora_tabs', $content_models, $pid); + $hook_tabs = module_invoke_all('islandora_tabs', $content_models, $pid, $page_number); $cmodels_tabs = array_merge($cmodels_tabs, $object_details, $hook_tabs); return tabs_render($cmodels_tabs); From 6d6342c269e4d7ca0168c4510e10d22303dba374 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 1 May 2012 14:20:46 -0300 Subject: [PATCH 15/19] Truncate titles for regular display to 60 character +/- a word. Should make the length an actual configurable value... Shouldn't be hard, though. --- CollectionClass.inc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CollectionClass.inc b/CollectionClass.inc index 18d5a107..b027ac4c 100644 --- a/CollectionClass.inc +++ b/CollectionClass.inc @@ -687,23 +687,27 @@ class CollectionClass { $per_page = 20; //XXX: Make this configurable. $pager_name = 0; $total = count($sparql_results); - $pager_page = self::hackPager($pager_name, $per_page, $total); + $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']; + $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, $title, $title, array(), FALSE); + "$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($title, $obj_path, array('attributes' => array('class' => 'results-text'))), + )) . l($truncated_title, $obj_path, array('attributes' => array('class' => 'results-text'))), ); } if (!$results) { From f51cdfe115b720d8b26c77ff05d6cce6b945e0a7 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 1 May 2012 14:22:19 -0300 Subject: [PATCH 16/19] Use hook_islandora_tabs() to add ALL the tabs. ... Including those provided by islandora proper. --- fedora_repository.module | 109 +++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/fedora_repository.module b/fedora_repository.module index a9209294..fec7256e 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -951,6 +951,63 @@ function makeObject($pid, $dsID) { $objectHelper->makeObject($pid, $dsID); } +/** + * 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( + '#type' => 'tabset', + ); + + 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(); + if ($object_details['fedora_object_details']['#selected'] == TRUE) { + foreach (element_children($cmodels_tabs) as $key) { + $cmodels_tabs[$key]['#selected'] = FALSE; + } + } + } + else { + $object_details = array(); + } + + return array_merge($cmodels_tabs, $object_details); +} + /** * 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 @@ -984,7 +1041,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(); @@ -1023,57 +1080,19 @@ 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', - ); - 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, - ); - } - } -// Add a 'manage object' tab for all objects, where detailed list of content is shown. - $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(); - 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, $page_number); - $cmodels_tabs = array_merge($cmodels_tabs, $object_details, $hook_tabs); - + + $cmodels_tabs = array( + '#type' => 'tabset', + ); + + $cmodels_tabs = array_merge($cmodels_tabs, $hook_tabs); return tabs_render($cmodels_tabs); } From 67bd855852f654155ac1c68c2e5310e48da54911 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 1 May 2012 14:46:45 -0300 Subject: [PATCH 17/19] Introduce hook_islandora_tabs_alter(). Called just before return of drupal_render()'d markup. Passed the tabset and associative array of the parameters with which hook_islandora_tabs() was called; that is: array( 'content_models' => {an array of ContentModel objects}, 'pid' => {the PID of the object being rendered}, 'page' => {the page of the object to be displayed}, ) --- fedora_repository.module | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fedora_repository.module b/fedora_repository.module index fec7256e..7a1c7946 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -1086,13 +1086,24 @@ function fedora_repository_get_items($pid = NULL, $dsId = NULL, $collection = NU $content_models = $objectHelper->get_content_models_list($pid); + //Get the tabs from all modules... $hook_tabs = module_invoke_all('islandora_tabs', $content_models, $pid, $page_number); $cmodels_tabs = array( '#type' => 'tabset', ); - $cmodels_tabs = array_merge($cmodels_tabs, $hook_tabs); + + //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); + return tabs_render($cmodels_tabs); } From 828c6965f7973fa52fea3c2a0e1f4d6e49678aba Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 1 May 2012 15:10:09 -0300 Subject: [PATCH 18/19] Use hook_islandora_tabs_alter() to ensure that fedora_object_details tab remains selected. --- fedora_repository.module | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/fedora_repository.module b/fedora_repository.module index 7a1c7946..a1151afd 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -994,20 +994,36 @@ function fedora_repository_islandora_tabs($content_models, $pid, $page_number) { //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 (element_children($cmodels_tabs) as $key) { - $cmodels_tabs[$key]['#selected'] = FALSE; - } - } - } - else { - $object_details = array(); + $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; + } + } + } +} + /** * 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 From 1463c78a382e90060c8954855a4a012fe20d1976 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 1 May 2012 15:52:04 -0300 Subject: [PATCH 19/19] Improve code documentation. --- fedora_repository.module | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/fedora_repository.module b/fedora_repository.module index a1151afd..7235aa36 100644 --- a/fedora_repository.module +++ b/fedora_repository.module @@ -741,7 +741,7 @@ function fedora_repository_replace_stream_form_submit($form, &$form_state) { $dsLabel = $form_state['values']['dsLabel']; $streamUrl = ($file !== NULL) ? - url($file->filepath, array('absolute' => TRUE)): + $file->filepath: url($form_state['values']['reference'], array('absolute' => TRUE)); // Remove the original file extension from the label and add the new one @@ -751,10 +751,9 @@ function fedora_repository_replace_stream_form_submit($form, &$form_state) { substr($streamUrl, strrpos($streamUrl, '.')); // Add the file extention to the end of the label. } - - $dformat = $form_state['storage']['mime_type']; + module_load_include('inc', 'fedora_repository', 'api/fedora_item'); $item = new Fedora_Item($pid); $item->modify_datastream($streamUrl, $dsid, $dsLabel, $dformat); @@ -966,9 +965,7 @@ function makeObject($pid, $dsID) { * drupal_render(). */ function fedora_repository_islandora_tabs($content_models, $pid, $page_number) { - $cmodels_tabs = array( - '#type' => 'tabset', - ); + $cmodels_tabs = array(); foreach ($content_models as $content_model) { $content_model_fieldset = $content_model->displayExtraFieldset($pid, $page_number); @@ -1025,17 +1022,26 @@ function fedora_repository_islandora_tabs_alter(&$tabs, $params) { } /** - * 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. + * 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'); @@ -1108,7 +1114,7 @@ function fedora_repository_get_items($pid = NULL, $dsId = NULL, $collection = NU $cmodels_tabs = array( '#type' => 'tabset', ); - $cmodels_tabs = array_merge($cmodels_tabs, $hook_tabs); + $cmodels_tabs += $hook_tabs; //Assemble parameters, to pass during alter $params = array(