Browse Source

Initial ingest multipage process, also cleanup.

pull/203/head
Nigel Banks 12 years ago
parent
commit
080440ce7a
  1. 11
      admin/islandora.admin.inc
  2. 16
      includes/DublinCore.inc
  3. 25
      includes/IslandoraTuque.inc
  4. 0
      includes/MimeDetect.inc
  5. 221
      includes/add_datastream.form.inc
  6. 35
      includes/breadcrumb.inc
  7. 462
      includes/datastream.inc
  8. 63
      includes/delete_datastream.form.inc
  9. 61
      includes/delete_object.form.inc
  10. 409
      includes/globals.inc
  11. 47
      includes/ingest-menu.inc
  12. 387
      includes/ingest.form.inc
  13. 62
      includes/ingest.menu.inc
  14. 235
      includes/islandora.ingest.inc
  15. 116
      includes/object_properties.form.inc
  16. 125
      includes/object_properties.inc
  17. 138
      includes/purge.form.inc
  18. 153
      includes/solution_packs.inc
  19. 85
      includes/utilities.inc
  20. 12
      islandora.api.php
  21. 4
      islandora.info
  22. 5
      islandora.install
  23. 455
      islandora.module
  24. 2
      theme/islandora-object-edit.tpl.php
  25. 10
      theme/islandora-object.tpl.php
  26. 5
      theme/islandora.theme.inc

11
admin/islandora.admin.inc

@ -11,18 +11,10 @@
* @return array * @return array
*/ */
function islandora_repository_admin($form, &$form_state) { function islandora_repository_admin($form, &$form_state) {
module_load_include('inc', 'islandora', 'includes/tuque');
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
// add css
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css'); drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
if (!IslandoraTuque::exists()) {
IslandoraTuque::getError();
return;
}
$form = array(); $form = array();
if (isset($form_state['values']['islandora_base_url'])) { if (isset($form_state['values']['islandora_base_url'])) {
$url = $form_state['values']['islandora_base_url']; $url = $form_state['values']['islandora_base_url'];
} }
@ -30,7 +22,6 @@ function islandora_repository_admin($form, &$form_state) {
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora'); $url = variable_get('islandora_base_url', 'http://localhost:8080/fedora');
} }
module_load_include('inc', 'islandora', 'includes/tuque');
$connection = new IslandoraTuque(NULL, $url); $connection = new IslandoraTuque(NULL, $url);
try { try {
$info = $connection->api->a->describeRepository(); $info = $connection->api->a->describeRepository();
@ -156,7 +147,6 @@ function islandora_repository_admin($form, &$form_state) {
function islandora_update_url_div($form, $form_state) { function islandora_update_url_div($form, $form_state) {
unset($form_state['submit_handlers']); unset($form_state['submit_handlers']);
$form_state['rebuild'] = TRUE; $form_state['rebuild'] = TRUE;
return $form['islandora_tabs']['islandora_general']['wrapper']; return $form['islandora_tabs']['islandora_general']['wrapper'];
} }
@ -166,6 +156,5 @@ function islandora_update_url_div($form, $form_state) {
function islandora_update_namespace_div($form, $form_state) { function islandora_update_namespace_div($form, $form_state) {
unset($form_state['submit_handlers']); unset($form_state['submit_handlers']);
$form_state['rebuild'] = TRUE; $form_state['rebuild'] = TRUE;
return $form['islandora_tabs']['islandora_namespace']['wrapper']; return $form['islandora_tabs']['islandora_namespace']['wrapper'];
} }

16
includes/islandora_dublin_core.inc → includes/DublinCore.inc

@ -10,7 +10,7 @@
/** /**
* Dublin Core Class * Dublin Core Class
*/ */
class Dublin_Core { class DublinCore {
public $dc = array( public $dc = array(
'dc:title' => array(), 'dc:title' => array(),
@ -32,11 +32,11 @@ class Dublin_Core {
public $owner; public $owner;
/** /**
* Constructs a Dublin_Core object from a Fedora_Item object and populates * Constructs a DublinCore object from a Fedora_Item object and populates the $dc array.
* the $dc array. *
* @param <type> $item * @param string $dc_xml
*/ */
function Dublin_Core($dc_xml = NULL) { function DublinCore($dc_xml = NULL) {
if (!empty($dc_string)) { if (!empty($dc_string)) {
$this->dc = self::import_from_xml_string($dc_xml); $this->dc = self::import_from_xml_string($dc_xml);
} }
@ -134,14 +134,15 @@ class Dublin_Core {
/** /**
* Creates a new instance of the class by parsing dc_xml * Creates a new instance of the class by parsing dc_xml
*
* @param string $dc_xml * @param string $dc_xml
* @return Dublin_Core * @return DublinCore
*/ */
static function import_from_xml_string($dc_xml) { static function import_from_xml_string($dc_xml) {
$dc_doc = new DomDocument(); $dc_doc = new DomDocument();
if ($dc_doc->loadXML($dc_xml)) { if ($dc_doc->loadXML($dc_xml)) {
$oai_dc = $dc_doc->getElementsByTagNameNS('http://purl.org/dc/elements/1.1/', '*'); $oai_dc = $dc_doc->getElementsByTagNameNS('http://purl.org/dc/elements/1.1/', '*');
$new_dc = new Dublin_Core(); $new_dc = new DublinCore();
foreach ($oai_dc as $child) { foreach ($oai_dc as $child) {
array_push($new_dc->dc[$child->nodeName], $child->nodeValue); array_push($new_dc->dc[$child->nodeName], $child->nodeValue);
} }
@ -153,4 +154,3 @@ class Dublin_Core {
} }
} }

25
includes/tuque.inc → includes/IslandoraTuque.inc

@ -2,32 +2,10 @@
/** /**
* @file * @file
*
* This file contains a class to include the Tuque php library. * This file contains a class to include the Tuque php library.
*/ */
$islandora_module_path = drupal_get_path('module', 'islandora');
//do this until we expost these in a module or library
@include_once 'sites/all/libraries/tuque/Datastream.php';
@include_once 'sites/all/libraries/tuque/FedoraApi.php';
@include_once 'sites/all/libraries/tuque/FedoraApiSerializer.php';
@include_once 'sites/all/libraries/tuque/Object.php';
@include_once 'sites/all/libraries/tuque/RepositoryConnection.php';
@include_once 'sites/all/libraries/tuque/Cache.php';
@include_once 'sites/all/libraries/tuque/RepositoryException.php';
@include_once 'sites/all/libraries/tuque/Repository.php';
@include_once 'sites/all/libraries/tuque/FedoraRelationships.php';
@include_once "$islandora_module_path/libraries/tuque/Datastream.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraApi.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraApiSerializer.php";
@include_once "$islandora_module_path/libraries/tuque/Object.php";
@include_once "$islandora_module_path/libraries/tuque/RepositoryConnection.php";
@include_once "$islandora_module_path/libraries/tuque/Cache.php";
@include_once "$islandora_module_path/libraries/tuque/RepositoryException.php";
@include_once "$islandora_module_path/libraries/tuque/Repository.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraRelationships.php";
class IslandoraTuque { class IslandoraTuque {
/** /**
@ -96,4 +74,3 @@ class IslandoraTuque {
drupal_set_message(filter_xss($message), 'error', FALSE); drupal_set_message(filter_xss($message), 'error', FALSE);
} }
} }

0
includes/mime.detect.inc → includes/MimeDetect.inc

221
includes/add_datastream.form.inc

@ -0,0 +1,221 @@
<?php
/**
* @file
*
* Functions for generating/validating/submitting the add datastream form.
*/
/**
* The admin add datastream form.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraObject $object
* The object to be deleted.
*
* @return array
* The drupal form definition.
*/
function islandora_add_datastream_form(array $form, array &$form_state, FedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/content_model');
form_load_include($form_state, 'inc', 'islandora', 'includes/add_datastream.form');
$form_state['object'] = $object;
$form_state['datastream_requirements'] = islandora_get_missing_datastreams_requirements($object);
$unused_datastreams = array_keys($form_state['datastream_requirements']);
$unused_datastreams = array_map(function($o) { return "'$o'"; }, $unused_datastreams);
$unused_datastreams = implode(', ', $unused_datastreams);
$upload_size = min((int)ini_get('post_max_size'), (int)ini_get('upload_max_filesize'));
return array(
'#redirect' => "islandora/object/{$object->id}",
'#attributes' => array(
'enctype' => 'multipart/form-data'
),
'fieldset' => array(
'#type' => 'fieldset',
'#title' => 'Add a datastream',
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'dsid' => array(
'#title' => 'Datastream ID',
'#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.' .
'Datastreams that are defined by the content model don\'t currently exist: <b>@unused_dsids</b>.',
array('@unused_dsids' => $unused_datastreams)
),
'#type' => 'textfield',
'#size' => 64,
'#maxlength' => 64,
'#required' => TRUE,
'#element_validate' => array(
'islandora_add_datastream_form_field_is_not_an_existing_datastream_id',
'islandora_add_datastream_form_field_starts_with_a_letter',
'islandora_add_datastream_form_field_is_valid_dsid',
),
'#autocomplete_path' => "islandora/object/{$object->id}/manage/datastreams/add/autocomplete"
),
'label' => array(
'#title' => 'Datastream Label',
'#required' => TRUE,
'#size' => 64,
'#maxlength' => 64,
'#description' => t('A Human readable label'),
'#type' => 'textfield',
'#element_validate' => array('islandora_add_datastream_form_field_does_not_contain_a_forward_slash')
),
'file' => array(
'#type' => 'managed_file',
'#required' => TRUE,
'#title' => t('Upload Document'),
'#size' => 48,
'#description' => t('Select a file to upload.<br/>Files must be less than <b>!size MB.</b>', array('!size' => $upload_size)),
'#default_value' => isset($form_state['values']['files']) ? $form_state['values']['files'] : NULL,
'#upload_location' => 'temporary://',
'#upload_validators' => array(
'file_validate_extensions' => array(NULL),
'file_validate_size' => array($upload_size * 1024 * 1024), // Assume its specified in MB
),
),
'submit' => array(
'#type' => 'submit',
'#value' => t('Add Datastream')
),
)
);
}
/**
* Checks if the given form field doesn't already repersent a Datastream ID.
*
* @param array $element
* The form field to check.
* @param array $form_state
* The Drupal form state.
* @param array $form
* The Drupal form.
*/
function islandora_add_datastream_form_field_is_not_an_existing_datastream_id(array $element, array &$form_state, array $form) {
if (isset($form_state['object'][$element['#value']])) {
form_error($element, t("!title already exists in the object.", array('!title' => $element['#title'])));
}
}
/**
* Checks if the given form field starts with a letter.
*
* @param array $element
* The form field to check.
* @param array $form_state
* The Drupal form state.
* @param array $form
* The Drupal form.
*/
function islandora_add_datastream_form_field_starts_with_a_letter(array $element, array &$form_state, array $form) {
if (!(preg_match("/^[a-zA-Z]/", $element['#value']))) {
form_error($element, t("!title has to start with a letter.", array('!title' => $element['#title'])));
}
}
/**
* Checks if the given form field contains only valid characters for a datstream id.
*
* @param array $element
* The form field to check.
* @param array $form_state
* The Drupal form state.
* @param array $form
* The Drupal form.
*/
function islandora_add_datastream_form_field_is_valid_dsid(array $element, array &$form_state, array $form) {
module_load_include('inc', 'islandora', 'includes/utilities');
if (!islandora_is_valid_dsid($element['#value'])) {
form_error($element, t("!title contains invalid characters.", array('!title' => $element['#title'])));
}
}
/**
* Checks if the given form field contains a "/" character.
*
* @param array $element
* The form field to check.
* @param array $form_state
* The Drupal form state.
* @param array $form
* The Drupal form.
*/
function islandora_add_datastream_form_field_does_not_contain_a_forward_slash(array $element, array &$form_state, array $form) {
if (strpos($element['#value'], '/') !== FALSE) {
form_error($element, t('!title cannot contain a "/" character.', array('!title' => $element['#title'])));
}
}
/**
* Checks if the given datastream id requires that the upload file be of a certian MIME type.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_add_datastream_form_validate(array $form, array &$form_state) {
$file = file_load($form_state['values']['file']);
$dsid = $form_state['values']['dsid'];
if (isset($form_state['datastream_requirements'][$dsid]) && $file) {
$allowed_types = $form_state['datastream_requirements'][$dsid]['mime'];
$mime_detect = new MimeDetect();
$allowed_extensions = array_map(array($mime_detect, 'getExtension'), $allowed_types);
$errors = file_validate_extensions($file, implode(' ', $allowed_extensions));
if (count($errors) > 0) {
form_set_error('file', $errors[0]);
}
}
}
/**
* Adds the new datastream based on the submitted values, only creates managed datastreams at the moment.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_add_datastream_form_submit(array $form, array &$form_state) {
$object = $form_state['object'];
$form_state['redirect'] = "islandora/object/{$object->id}";
$file = file_load($form_state['values']['file']);
try {
$ds = $object->constructDatastream($form_state['values']['dsid'], 'M');
$ds->label = $form_state['values']['label'];
$ds->mimetype = $file->filemime;
$path = drupal_realpath($file->uri);
$ds->setContentFromFile($path);
$object->ingestDatastream($ds);
file_delete($file);
} catch (exception $e) {
drupal_set_message(t('@message', array('@message' => check_plain($e->getMessage()))), 'error');
file_delete($file); // Make sure to delete anyways.
return;
}
drupal_set_message(t("Successfully Added Datastream!"));
}
/**
* Callback for an autocomplete field in the admin add datastream form. It lists the missing required (may be optional) datastreams.
*
* @param FedoraObject $object
* The object used to check for missing required datastreams used to populate the options in this callback.
* @param string $query
* The user query to match against the missing required datastreams.
*/
function islandora_add_datastream_form_autocomplete_callback(FedoraObject $object, $query = '') {
module_load_include('inc', 'islandora', 'includes/content_model');
$dsids = array_keys(islandora_get_missing_datastreams_requirements($object));
$dsids = array_combine($dsids, $dsids);
$query = trim($query);
if (!empty($query)) {
$dsids = array_filter($dsids, function($id) use($query) { return stripos($id, $query) !== FALSE; });
}
drupal_json_output($dsids);
}

35
includes/breadcrumb.inc

@ -2,23 +2,31 @@
/** /**
* @file * @file
*
* This file contains functions to create breadcrumbs on Islandora object pages. * This file contains functions to create breadcrumbs on Islandora object pages.
*/ */
/** /**
* Callback function to get the breadcrumbs for an object page * Get an array of links to be passed to drupal_set_breadcrumb(). This is used for generating the bread-crumbs for the view object page.
*
* Each link in the bread-crumbs represents a member of the given objects ancestry
* which is identified by any of the following RELS-EXT terms (isMemberOf,isMemberOfCollection,isPartOf).
*
* @param FedoraObject $object
* An object whose ancestry will be mapped to bread-crumbs.
*
* @see drupal_set_breadcrumb()
*
* @return array
* Array of links, starting with most distant ancestor proceeding up to but not including the given object. For use in the function drupal_set_breadcrumb().
*/ */
function islandora_get_breadcrumbs($object) { function islandora_get_breadcrumbs($object) {
$breadcrumbs = array(); $breadcrumbs = array();
islandora_get_breadcrumbs_recursive($object->id, $breadcrumbs, $object->repository); islandora_get_breadcrumbs_recursive($object->id, $breadcrumbs, $object->repository);
if (isset($breadcrumbs[0])) { // Remove the actual object.
if (isset($breadcrumbs[0])) {
unset($breadcrumbs[0]); unset($breadcrumbs[0]);
} }
$breadcrumbs = array_reverse($breadcrumbs); $breadcrumbs = array_reverse($breadcrumbs);
return $breadcrumbs; return $breadcrumbs;
} }
@ -27,14 +35,17 @@ function islandora_get_breadcrumbs($object) {
* *
* @todo Make fully recursive... * @todo Make fully recursive...
* *
* @global type $base_url * @todo Could use some clean up, can't be called multiple times safely due to the use of static variables.
* @param type $pid *
* @param type $breadcrumbs * @param string $pid
* @param type $level * THe object id whose parent will be fetched for the next link.
* @param array $breadcrumbs
* The list of existing bread-crumb links in reverse order.
* @param FedoraRepository $repository
* The fedora repository.
*/ */
function islandora_get_breadcrumbs_recursive($pid, &$breadcrumbs, $repository) { function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRepository $repository) {
// Before executing the query, we hve a base case of accessing the top-level collection // Before executing the query, we hve a base case of accessing the top-level collection
global $base_url;
static $max_level = 10; static $max_level = 10;
static $level = -1; static $level = -1;

462
includes/datastream.inc

@ -2,454 +2,94 @@
/** /**
* @file * @file
*
* This file contains the admin form and callback functions for datastream manipulations. * This file contains the admin form and callback functions for datastream manipulations.
*/ */
define('DS_COMP_STREAM', 'DS-COMPOSITE-MODEL'); /**
* Callback to download the given datastream to the users computer.
*
* @param FedoraDatastream $datastream
* The datastream to download.
*/
function islandora_download_datastream(FedoraDatastream $datastream) {
islandora_view_datastream($datastream, TRUE);
}
/** /**
* Callback function to view or download a datastream. * Callback function to view or download a datastream.
* *
* @global object $user * @note
* @param string $object_id * This function calls exit().
* @param string $dsid *
* @return stream * @param FedoraDatastream $datastream
* prints datastream to browser * The datastream to view/download.
* @param boolean $download
* If TRUE the file is download to the user computer for viewing otherwise it will attempt to display in the browser natively.
*/ */
function islandora_view_datastream($object, $dsid, $method = 'view') { function islandora_view_datastream(FedoraDatastream $datastream, $download = FALSE) {
// if the object exists but the datastream doesn't
if (!isset($object[$dsid])) {
return drupal_not_found();
}
header_remove('Cache-Control'); header_remove('Cache-Control');
header_remove('Expires'); header_remove('Expires');
header('Content-type: ' . $object[$dsid]->mimetype); header('Content-type: ' . $datastream->mimetype);
if ($object[$dsid]->controlGroup == 'M' || $object[$dsid]->controlGroup == 'X') { if ($datastream->controlGroup == 'M' || $datastream->controlGroup == 'X') {
header('Content-length: ' . $object[$dsid]->size); header('Content-length: ' . $datastream->size);
} }
if ($download) {
if ($method == 'download') { header("Content-Disposition: attachment; filename=\"" . $datastream->label);
header("Content-Disposition: attachment; filename=\"" . $object[$dsid]->label);
} }
// Disable page caching
drupal_page_is_cacheable(FALSE); drupal_page_is_cacheable(FALSE);
// Try not to load the file into PHP memory!
// Try not to load the file into PHP memory
$file = drupal_tempnam(file_directory_temp(), 'islandora'); $file = drupal_tempnam(file_directory_temp(), 'islandora');
$object[$dsid]->getContent($file); $datastream->getContent($file);
readfile($file); readfile($file);
drupal_unlink($file); drupal_unlink($file);
exit(); exit();
} }
/** /**
* For a given object, return all parent collections. * Get the human readable size of the given datastream.
*/
function islandora_datastream_get_parents($islandora_object) {
$parent_collections = array();
try {
$repository = $islandora_object->repository;
$collections1 = $islandora_object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOfCollection');
$collections2 = $islandora_object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOf');
}
catch (RepositoryException $e) {
$collections1 = array();
$collections2 = array();
}
$collections = array_merge($collections1, $collections2);
foreach ($collections as $collection) {
try {
$pid = $collection['object']['value'];
$object = $repository->getObject($collection['object']['value']);
$parent_collections[$pid] = array();
$parent_collections[$pid]['object'] = $object;
$parent_collections[$pid]['url'] = 'islandora/object/' . $object->id;
$parent_collections[$pid]['label'] = $object->label;
$parent_collections[$pid]['label_link'] = l($parent_collections[$pid]['label'], $parent_collections[$pid]['url']);
}
catch (RepositoryException $e) {
}
}
return $parent_collections;
}
/**
* *
* @param array $arr * @param FedoraDatastream $datastream
* an array of dsids that are defined by this objects cmodels * The datastream to check.
* @param string $ds_comp_stream
* the dscomposite stream as xml
*/
function islandora_get_defined_dsids_array(&$arr, $ds_comp_stream) {
$sxml = new SimpleXMLElement($ds_comp_stream);
foreach ($sxml->dsTypeModel as $ds) {
//$arr[$ds['ID']]
$mimes = array();
foreach ($ds->form as $form) {
$mimetype = (string) $form['MIME'];
$mimes[] = $mimetype;
}
$dsid = (string) $ds['ID'];
if ($dsid != 'AUDIT') {
$arr[(string) $ds['ID']] = $mimes;
}
}
}
/**
* *
* @global type $user * @return string
* @param string $object_id * A human readable size of the given datastream, or '-' if the size could not be determined.
* @return string|array
*/ */
function islandora_get_unused_dsids($object) { function islandora_datastream_get_human_readable_size(FedoraDatastream $datastream) {
module_load_include('inc', 'islandora', 'includes/utilities');
$defined_dsids = array(); $size_is_calculatable = $datastream->controlGroup == 'M' || $datastream->controlGroup == 'X';
return $size_is_calculatable ? islandora_convert_bytes_to_human_readable($datastream->size) : '-';
if (!$object) {
return $defined_dsids;
}
$models = $object->models;
if (isset($models)) {
foreach ($models as $model) {
try {
$model_object = $object->repository->getObject($model);
if (isset($model_object[DS_COMP_STREAM])) {
$dscomposite_stream = $model_object[DS_COMP_STREAM]->content;
islandora_get_defined_dsids_array($defined_dsids, $dscomposite_stream);
}
} catch (Exception $e) {
//do nothing as other objects may have a dscompsite stream
}
}
}
foreach ($defined_dsids as $key => $value) {
if (isset($object[$key])) {
unset($defined_dsids[$key]); //ds exists in the object so don't show in the dropdown
}
}
return $defined_dsids;
}
/**
* buids the default add datastream form
* @param string $object_id
* @param array $form_state
* @return array
* a form ready to be rendered with a call to Drupal render
*/
function islandora_get_add_datastream_form($object, &$form_state) {
$unused_dsids = islandora_get_unused_dsids($object);
$form = array();
$form['add_fieldset'] = array(
'#type' => 'fieldset',
'#title' => 'Add a datastream',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['add_fieldset']['add_datastream_label'] = array(
'#value' => t('<br /><h3>Add Datastream:</h3>'),
'#weight' => -10,
);
$form['pid'] = array(
'#type' => 'hidden',
'#value' => "$object->id"
);
$form['add_fieldset']['stream_label'] = array(
'#title' => 'Datastream Label',
'#required' => 'TRUE',
'#description' => t('A Human readable label'),
'#type' => 'textfield'
);
$form['#attributes']['enctype'] = 'multipart/form-data';
$form['add_fieldset']['add-stream-file-location'] = array(
'#type' => 'file',
'#title' => t('Upload Document'),
'#size' => 48,
// '#required'=>'TRUE',
'#description' => t('The file to upload.')
);
$form['#redirect'] = "islandora/object/$object->id/";
$form['add_fieldset']['submit'] = array(
'#type' => 'submit',
'#value' => t('Add Datastream')
);
if (!empty($unused_dsids)) {
$dsids_for_form = array();
foreach ($unused_dsids as $key => $value) {
$dsids_for_form[$key] = $key;
}
$form['add_fieldset']['stream_id'] = array(
'#type' => 'select',
'#title' => t('Datastream ID'),
'#default_value' => variable_get('feed_item_length', 'teaser'),
'#weight' => '-1',
'#description' => t('Datastream IDs defined by the content model.'),
);
$form['add_fieldset']['stream_id']['#options'] = $dsids_for_form;
}
else {
$form['add_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.'),
'#type' => 'textfield',
'#weight' => -1,
);
}
return $form;
}
/**
* Default implmentation currently only does M (managed datastreams)
* other modules can hook form alter to add other functionality
* @global string $base_url
* @global object $user
* Drupal user
* @param array $form
* @param array $form_state
* @return type
*/
function islandora_add_datastream_form_submit($form, &$form_state) {
global $base_url;
if (!empty($form_state['submit']) && $form_state['submit'] == 'OK') {
$form_state['rebuild'] = TRUE;
return;
}
module_load_include('inc', 'islandora', 'includes/mime.detect');
$mimetype = new MimeDetect();
$file = $form_state['values']['add-stream-file-location'];
$file = drupal_realpath($file);
$object_id = $form_state['values']['pid'];
$dsid = $form_state['values']['stream_id'];
$ds_label = $form_state['values']['stream_label'];
$dformat = $mimetype->getMimeType($file);
$control_group = "M";
try {
$fedora_object = islandora_object_load($object_id);
$ds = $fedora_object->constructDatastream($dsid, $control_group);
$ds->label = $ds_label;
$ds->mimetype = $dformat;
$ds->setContentFromFile($file);
$fedora_object->ingestDatastream($ds);
$d_file = file_load($form_state['values']['fid']);
file_delete($d_file);
} catch (exception $e) {
drupal_set_message(t('@message', array('@message' => check_plain($e->getMessage()))), 'error');
return;
}
drupal_set_message(t("Successfully Added Datastream!"));
drupal_goto("islandora/object/$object_id");
} }
/** /**
* validates this datastream id against its allowed mimetypes in the dscomposite * Get either the 'view' or 'download' url for the given datastream if possible.
* of its content models. *
* @param array $form * @param FedoraDatastream $datastream
* @param array $form_state * The datastream to generated the url to.
* @return boolean *
* @return string
* either the 'view' or 'download' url for the given datastream.
*/ */
function islandora_add_datastream_form_validate($form, &$form_state) { function islandora_datastream_get_url(FedoraDatastream $datastream, $type = 'download') {
module_load_include('inc', 'islandora', 'includes/mime.detect'); return $datastream->controlGroup == 'R' ? $datastream->url : "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/$type";
$mimetype = new MimeDetect();
if ($form_state['clicked_button']['#value'] == 'OK') {
$form_state['rebuild'] = TRUE;
return;
}
$dsid = $form_state['values']['stream_id'];
$ds_label = $form_state['values']['stream_label'];
if (drupal_strlen($dsid) > 64) {
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))));
return FALSE;
}
if (drupal_strlen($ds_label) > 64) {
form_set_error('', t('Data stream Label cannot be more than 64 characters.'));
return FALSE;
}
if (strpos($ds_label, '/')) {
form_set_error('', t('Data stream Label cannot contain a "/".'));
return FALSE;
}
$object_id = $form_state['values']['pid'];
$fedora_object = islandora_object_load($object_id);
if (isset($fedora_object[$dsid])) {
form_set_error('', t('Data stream ID already exists in object.'));
return FALSE;
}
$mimetype = new MimeDetect();
$object = islandora_object_load($form_state['values']['pid']);
$unused_dsids = islandora_get_unused_dsids($object);
if (isset($unused_dsids[$dsid])) {
$types_allowed = $unused_dsids[$dsid];
$arr = array();
foreach ($types_allowed as $type) {
$arr[] = $mimetype->getExtension($type);
}
}
else {
// @TODO: this is unsafe, should probably be fixed see:
// http://api.drupal.org/api/drupal/includes!file.inc/function/file_save_upload/7
$arr = array();
}
$file = file_save_upload('add-stream-file-location', array('file_validate_extensions' => $arr));
if ($file) {
$form_state['values']['add-stream-file-location'] = $file->uri;
$form_state['values']['fid'] = $file->fid; //so we can load it to delete later
}
else {
form_set_error('add-stream-file-location', t('There was no file uploaded'));
}
} }
/** /**
* buids the default add datastream form * Gets the delete link.
* @param string $object_id *
* @param array $form_state * @param FedoraDatastream $datastream
* @return array * The datastream to generated the url to.
* a form ready to be rendered with a call to Drupal render
*/ */
function islandora_add_datastream_form($form, &$form_state, $object) { function islandora_datastream_get_delete_link(FedoraDatastream $datastream) {
// Ensure we're loaded, in case AJAX stuff is ever added. $datastreams = module_invoke_all('islandora_undeletable_datastreams', $datastream->parent->models);
form_load_include($form_state, 'inc', 'islandora', 'includes/datastream'); if (in_array($datastream->id, $datastreams)) {
$unused_dsids = islandora_get_unused_dsids($object); //$defined_dsids;
$form = array();
$form['add_fieldset'] = array(
'#type' => 'fieldset',
'#title' => 'Add a datastream',
'#collapsible' => FALSE,
'#collapsed' => FALSE,
);
$form['add_fieldset']['add_datastream_label'] = array(
'#value' => t('<br /><h3>Add Datastream:</h3>'),
'#weight' => -10,
);
$form['pid'] = array(
'#type' => 'hidden',
'#value' => "$object->id"
);
$form['add_fieldset']['stream_label'] = array(
'#title' => 'Datastream Label',
'#required' => 'TRUE',
'#description' => t('A Human readable label'),
'#type' => 'textfield'
);
$form['#attributes']['enctype'] = 'multipart/form-data';
$form['add_fieldset']['add-stream-file-location'] = array(
'#type' => 'file',
'#title' => t('Upload Document'),
'#size' => 48,
// '#required'=>'TRUE',
'#description' => t('The file to upload.')
);
$form['#redirect'] = "islandora/object/$object->id/";
$form['add_fieldset']['submit'] = array(
'#type' => 'submit',
'#value' => t('Add Datastream')
);
$unused_dsids = islandora_get_unused_dsids($object);
$dsids_for_form = '';
$i = 0;
foreach ($unused_dsids as $key => $value) {
if ($i++) {
$dsids_for_form .= ", ";
}
$dsids_for_form .= "'$key'";
}
$form['add_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. Datastreams that are defined by the content model don\'t currently exist: <b>@unused_dsids</b>.', array(
'@unused_dsids' => $dsids_for_form,
)),
'#type' => 'textfield',
'#weight' => -1,
'#autocomplete_path' => "islandora/object/$object->id/manage/datastreams/add/autocomplete",
);
return $form;
}
function islandora_datastream_autocomplete_callback($object, $string = '') {
$dsids = islandora_get_unused_dsids($object);
$output = array();
foreach ($dsids as $id => $ds) {
if (trim($string) == '') {
$output[$id] = $id;
}
else {
$ret = stripos($id, $string);
if ($ret !== FALSE) {
$output[$id] = $id;
}
}
}
drupal_json_output($output);
}
function islandora_datastream_get_human_readable_size($ds) {
module_load_include('inc', 'islandora', 'includes/utilities');
// we return - if we don't have a size
if ($ds->controlGroup == 'M' || $ds->controlGroup == 'X') {
return islandora_convert_bytes_to_human_readable($ds->size);
}
else {
return '-';
}
}
function islandora_datastream_get_url($ds, $type = 'download') {
if ($ds->controlGroup == 'R') {
return $ds->url;
}
else {
return "islandora/object/{$ds->parent->id}/datastream/{$ds->id}/$type";
}
}
function islandora_datastream_get_delete_link($ds) {
$datastreams = module_invoke_all('islandora_undeletable_datastreams', $ds->parent->models);
if (in_array($ds->id, $datastreams)) {
return ''; return '';
} }
else { else {
return l(t('delete'), 'islandora/object/' . $ds->parent->id . '/datastream/' . $ds->id . '/delete'); return l(t('delete'), 'islandora/object/' . $datastream->parent->id . '/datastream/' . $datastream->id . '/delete');
} }
} }
function islandora_islandora_undeletable_datastreams($models) {
return array('DC');
}
function islandora_datastream_edit_get_link($object, $ds_id) { function islandora_datastream_edit_get_link($object, $ds_id) {
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $object, $ds_id); $edit_registry = module_invoke_all('islandora_edit_datastream_registry', $object, $ds_id);

63
includes/delete_datastream.form.inc

@ -0,0 +1,63 @@
<?php
/**
* @file
*
* This file contains the admin (confirmation) form and callback functions to delete/purge a datastream.
*/
/**
* The admin delete datastream form.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraDatastream $datastream
* The datastream to be deleted.
*
* @return array
* The drupal form definition.
*/
function islandora_delete_datastream_form(array $form, array &$form_state, FedoraDatastream $datastream) {
$form_state['datastream'] = $datastream;
return confirm_form($form,
t('Are you sure you want to delete the %dsid datastream?', array('%dsid' => $datastream->id)),
"islandora/object/{$datastream->parent->id}",
t('This action cannot be undone.'),
t('Delete'),
t('Cancel')
);
}
/**
* Submit handler for the delete datastream form. Purges/Delete's the given FedoraDatastream if possible.
*
* The ISLANDORA_PRE_PURGE_DATASTREAM_HOOK will query other modules as to whether the given FedoraDatastream
* should be: blocked from purging; state set to 'Deleted'; or purged.
*
* @see islanodra_delete_datastream().
*
* @param string $object_id
* ID of the object
* @param string $datastream_id
* ID of the datastream
*/
function islandora_delete_datastream_form_submit(array $form, array &$form_state) {
$datastream = $form_state['datastream'];
$datastream_id = $datastream->id;
$object = $datastream->parent;
$deleted = FALSE;
try {
$deleted = islandora_delete_datastream($datastream);
} catch (Exception $e) {
drupal_set_message(t('Error deleting %s datastream from object %o %e', array('%s' => $datastream_id, '%o' => $object->label, '%e' => $e->getMessage())), 'error');
}
if ($deleted) {
drupal_set_message(t('%d datastream sucessfully deleted from Islandora object %o', array('%d' => $datastream_id, '%o' => $object->label)));
}
else {
drupal_set_message(t('Error deleting %s datastream from object %o', array('%s' => $datastream_id, '%o' => $object->label)), 'error');
}
$form_state['redirect'] = "islandora/object/{$object->id}";
}

61
includes/delete_object.form.inc

@ -0,0 +1,61 @@
<?php
/**
* @file
*
* This file contains the admin (confirmation) form and callback functions to purge an object.
*/
/**
* The admin delete object form.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraObject $object
* The object to be deleted.
*
* @return array
* The drupal form definition.
*/
function islandora_delete_object_form(array $form, array &$form_state, FedoraObject $object) {
$form_state['object'] = $object;
return confirm_form($form,
t('Are you sure you want to delete %title?', array('%title' => $object->label)),
"islandora/object/$object->id",
t('This action cannot be undone.'),
t('Delete'),
t('Cancel')
);
}
/**
* Gives the option of deleting or purging and object.
*
* @note The description below probably applies to islanodra_object_purge() function...
*
* The default behaviour is to purge the object to reduce maintenance.
* If a solution pack wants to change this behaviour and have the object set to deleted then
* it can respond to the 'islandora_pre_purge_object' hook with an array containing the pair
* 'delete' => TRUE.
* Once the object has been deleted/purged then a second call lets the solution packs know that
* the object has been dealt with. In this call the object id and content models are sent out so
* that the solution packs can act on this news. There is no guarantee that the object still exists
* and so the object object isn't sent.
*
* @todo Clean Up!
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_delete_object_form_submit(array $form, array &$form_state) {
module_load_include('inc', 'islandora', 'includes/datastream');
$object = $form_state['object'];
$parents = islandora_get_parents_from_rels_ext($object);
$parent = array_pop($parents);
$form_state['redirect'] = isset($parent) ? "islandora/object/{$parent->id}" : 'islandora';
islandora_delete_object($object);
}

409
includes/globals.inc

@ -0,0 +1,409 @@
<?php
/**
* @file
*
* This file contains any functions meant to be part of the global space, ie. functions that and other modules will use without including a module file.
*/
/**
* Just a wrapper around fetchings the IslandoraTuque object, with some very basic error logging.
*
* @return IslandoraTuque
* A IslandoraTuque instance
*/
function islandora_get_tuque_connection() {
$tuque = &drupal_static(__FUNCTION__);
if (!$tuque) {
try {
$tuque = new IslandoraTuque();
} catch (Exception $e) {
drupal_set_message(t('Unable to connect to the repository %e', array('%e' => $e)), 'error');
}
}
return $tuque;
}
/**
* Gets the given object if found, NULL if it is inaccessible and FALSE if it was not found.
*
* @param string $object_id
* The identifier of the object to get.
*
* @return FedoraObject
* The object if found, NULL if it is inaccessible and FALSE if it was not found.
*/
function islandora_get_object_by_id($object_id) {
$tuque = islandora_get_tuque_connection();
if ($tuque) {
try {
$object = $tuque->repository->getObject($object_id);
drupal_alter('islandora_object', $object);
return $object;
} catch (Exception $e) {
if ($e->getCode() == '404') {
return FALSE;
} else {
return NULL;
}
}
}
else {
IslandoraTuque::getError();
}
return NULL; // Assuming access denied in all other cases for now.
}
/**
* Ingest the given object into Fedora calling its pre/post hooks as well.
*
* @param NewFedoraObject $object
* An ingestable FedoraObject.
*
* @return FedoraObject
* The ingested FedoraObject, after running the pre/post ingest hooks.
*/
function islandora_add_object(NewFedoraObject &$object) {
islandora_pre_add_object($object);
$object->repository->ingestObject($object);
islandora_post_add_object($object);
return $object;
}
/**
* Calls the ISLANDORA_PRE_INGEST_HOOK hooks.
*
* @param NewFedoraObject $object
* An ingestable FedoraObject.
*/
function islandora_pre_add_object(NewFedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_PRE_INGEST_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object);
}
}
/**
* Calls the ISLANDORA_POST_INGEST_HOOK hooks.
*
* @param FedoraObject $object
* A recently ingestable FedoraObject.
*/
function islandora_post_add_object(FedoraObject $object) {
foreach (islandora_build_hook_list(ISLANDORA_POST_INGEST_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object);
}
}
/**
* Deletes the given object into Fedora calling its pre/post hooks as well.
*
* @param FedoraObject $object
* An object to delete.
*
* @return FedoraObject
* The ingested FedoraObject, after running the pre/post ingest hooks.
*/
function islandora_delete_object(FedoraObject &$object) {
$object_id = $object->id;
$models = $object->models;
$action = islandora_pre_delete_object($object);
switch ($action) {
case 'blocked': // Do nothing.
return FALSE;
case 'delete': // Change the state to deleted.
$object->delete();
islandora_post_delete_object($object, $object_id, $models);
return TRUE;
default: // Purge
$object->repository->purgeObject($object_id);
islandora_post_delete_object($object_id, $models);
$object = NULL;
return TRUE;
}
islandora_post_delete_object($object);
return $object;
}
/**
* Calls the ISLANDORA_PRE_PURGE_OBJECT_HOOK hooks.
*
* @param FedoraObject $object
* The object that is about to be deleted.
*/
function islandora_pre_delete_object(FedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
$results = array();
foreach (islandora_build_hook_list(ISLANDORA_PRE_PURGE_OBJECT_HOOK, $object->models) as $hook) {
$results = array_merge_recursive($results, module_invoke_all($hook, $object));
}
$action = (isset($results['block']) && $results['block']) ? 'block' : FALSE;
$action = (!$action && isset($results['delete']) && $results['delete']) ? 'delete' : $action;
$action = !$action ? 'purge' : $action;
return $action;
}
/**
* Calls the ISLANDORA_POST_INGEST_HOOK hooks.
*
* @param string $object_id
* The object id of an the recently deleted object.
* @param array $models
* The list of content models the delete object subsribed to.
*/
function islandora_post_delete_object($object_id, array $models) {
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_POST_PURGE_OBJECT_HOOK, $models) as $hook) {
module_invoke_all($hook, $object_id, $models);
}
}
/**
* Delete's/Purges the given datastream.
*
* @throws Exception
* Which types are undefined, but more than likely because of the hooks there will be several kinds.
*
* @param FedoraDatastream $datastream
* The datastream to delete.
*
* @return boolean
* TRUE is returned if the datastream was Deleted/Purged, FALSE if it was blocked.
*/
function islandora_delete_datastream(FedoraDatastream &$datastream) {
$datastream_id = $datastream->id;
$object = $datastream->parent;
$action = islandora_pre_delete_datastream($datastream);
switch ($action) {
case 'blocked': // Do nothing.
return FALSE;
case 'delete': // Change the state to deleted.
$object[$datastream_id]->state = 'D';
islandora_post_delete_datastream($object, $datastream_id); // @todo Differentiate between delete/purge in the hooks.
return TRUE;
default: // Purge
$object->purgeDatastream($datastream_id);
islandora_post_delete_datastream($object, $datastream_id);
$datastream = NULL;
return TRUE;
}
}
/**
* The default behaviour is to 'purge' the datastream but this can be overridden by modules that implement
* the 'islandora_pre_purge_datastream' hook.
*
* @todo make this an alter.
*
* The returned array can include a 'block' => TRUE
* pair which will prevent the datastream from being deleted if it particularly needed for
* a certain function. Returning 'delete' => TRUE will cause the datastream to be put into
* a deleted state.
*
* @param FedoraDatastream $datastream
* The datastream to delete.
*
* @return string
* The action to take when deleting the given datastream, either 'purge', 'delete', or 'block'.
*/
function islandora_pre_delete_datastream(FedoraDatastream $datastream) {
module_load_include('inc', 'islandora', 'includes/utilities');
$results = array();
foreach (islandora_build_hook_list(ISLANDORA_PRE_PURGE_DATASTREAM_HOOK, $datastream->parent->models) as $hook) {
$results = array_merge_recursive($results, module_invoke_all($hook, $datastream)); // @note Not sure this will work the greatest, probably an alter would be better...
}
$action = (isset($results['block']) && $results['block']) ? 'block' : FALSE;
$action = (!$action && isset($results['delete']) && $results['delete']) ? 'delete' : $action;
$action = !$action ? 'purge' : $action;
return $action;
}
/**
* Calls the post purge datastream hooks.
*
* @todo Should differentiate between purging/deleting.
*
* @param FedoraObject $object
* The parent object of the deleted datastream.
* @param string $datastream_id
* The datastream id of the deleted datastream.
*/
function islandora_post_delete_datastream(FedoraObject $object, $datastream_id) {
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_POST_PURGE_DATASTREAM_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object, $datastream_id);
}
}
/**
* Gets any objects that the given object has a (isMemberOf, isMemberOfCollection) relationship with.
*
* This function gets its info from the RELS-EXT directly rather than through an risearch.
*
* @param FedoraObject $object
* The object whose parents will be returned.
*
* @return array
* An array of FedoraObject's that the given object has a (isMemberOf, isMemberOfCollection) relationship with.
*/
function islandora_get_parents_from_rels_ext(FedoraObject $object) {
try {
$collections = array_merge(
$object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOfCollection'),
$object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOf'));
}
catch (RepositoryException $e) {
return array();
} // @todo some logging would be nice, not sure what this throws.
$collections = array_map(function($o) { return islandora_get_object_by_id($o['object']['value']); }, $collections);
return array_filter($collections);
}
/**
* Checks what datastreams the object already has against its required datastreams as defined by its content models, and returns their intersection.
*
* @param FedoraObject $object
* The object which models will be used to determine what datastreams it should have.
*
* @return array
* The DS-COMPOSITE-MODEL defined datastreams that are required for the given object, but not already present.
*/
function islandora_get_missing_datastreams_requirements(FedoraObject $object) {
$datastreams = islandora_get_datastreams_requirements($object);
foreach ($datastreams as $dsid => $requirements) {
if (isset($object[$dsid])) {
unset($datastreams[$dsid]);
}
}
return $datastreams;
}
/**
* Checks the object's content model's for which datastream are expected to be used with this object, as defined by the DS-COMPOSITE-MODEL datastreams.
*
* For duplicate datastreams in the models, the first model defines the datastreams attributes regardless of what other models define.
* This should be undefined behavior according to the documentation.
* @see https://wiki.duraspace.org/display/FEDORA34/Fedora+Digital+Object+Model#FedoraDigitalObjectModel-ContentModelObjectCMODEL
*
* @param FedoraObject $object
* The object which models will be used to determine what datastreams it should have.
*
* @see islandora_get_required_datastreams_from_content_model() from more details on the return value.
*
* @return array
* The DS-COMPOSITE-MODEL defined datastreams that are required for the given object.
*/
function islandora_get_datastreams_requirements(FedoraObject $object) {
$dsids = array();
foreach ($object->models as $model) {
$model = islandora_get_object_by_id($model);
$dsids += islandora_get_datastreams_requirements_from_content_model($model);
}
unset($dsids['AUDIT']); // The AUDIT Datastream can not really be added, so it can't really be missing.
return $dsids;
}
/**
* Checks the given content model for which datastreams are required for subscribing objects, as defined by it's DS-COMPOSITE-MODEL datastream.
*
* @todo Add support for fetching the schema information.
*
* @param FedoraObject $object
* The content model whose DS-COMPOSITE-MODEL datastream will be used to determine what datastreams are required.
*
* @return array
* The DS-COMPOSITE-MODEL defined datastreams that are required for the given object.
*
* @code
* array(
* 'DC' => array(
* 'id' => 'DC',
* 'mime' => 'text/xml',
* 'optional' => FALSE,
* )
* )
* @endcode
*/
function islandora_get_datastreams_requirements_from_content_model(FedoraObject $object) {
if (empty($object[DS_COMP_STREAM])) {
return array();
}
$xml = new SimpleXMLElement($object[DS_COMP_STREAM]->content);
foreach ($xml->dsTypeModel as $ds) {
$dsid = (string) $ds['ID'];
$optional = strtolower((string) $ds['optional']);
$mime = array();
foreach ($ds->form as $form) {
$mime[] = (string) $form['MIME'];
}
$dsids[$dsid] = array(
'id' => $dsid,
'mime' => $mime,
'optional' => ($optional == 'true') ? TRUE : FALSE
);
}
return $dsids;
}
/**
* Prepare an ingestable object.
*
* @param string $namespace
* The namespace in which the PID for the new object will be created.
* @param string $label
* An optional label to apply to the object.
* @param array $datastreams
* A array of datastreams to add, where each datastream definition is an
* associative array containing:
* - dsid: The datastream ID.
* - label: An optional label for the datastream.
* - mimetype: A MIMEtype for the datastream; defaults to text/xml.
* - control_group: One of X, M, R and E; defaults to M.
* - datastream_file: A web-accessible path, for which we try to get an
* absolute path using url().
* @param array $content_models
* An array of content model PIDs to which the new object should subscribe.
* @param array $relationships
* An array of relationships, where each relationship is an associative array
* containing:
* - relationship: The predicate for the relationship, from the Fedora
* RELS-EXT namespace.
* - pid: The object for the relationship, to which we are creating the
* relationhsip.
*
* @return NewFedoraObject
* An ingestable NewFedoraObject.
*/
function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastreams = array(), $content_models = array(), $relationships = array()) {
$tuque = islandora_get_tuque_connection();
$object = isset($namespace) ? $tuque->repository->constructObject($namespace) : new NewFedoraObject(NULL, $tuque->repository);
$object->owner = isset($user->name) ? $user->name : $object->owner;
$object->label = isset($label) ? $label : $object->label;
foreach ($content_models as $content_model) {
$object->relationships->add(FEDORA_MODEL_URI, 'hasModel', $content_model);
}
foreach ($relationships as $relationship) {
$object->relationships->add(FEDORA_RELS_EXT_URI, $relationship['relationship'], $relationship['pid']);
}
foreach ($datastreams as $ds) {
$dsid = $ds['dsid'];
$label = isset($ds['label']) ? $ds['label'] : '';
$mimetype = isset($ds['mimetype']) ? $ds['mimetype'] : 'text/xml';
$control_group = (isset($ds['control_group']) && in_array($ds['control_group'], array('X', 'M', 'R', 'E'))) ? $ds['control_group'] : 'M'; // Default 'Managed'
$datastream_file = url($ds['datastream_file'], array('absolute' => TRUE));
$datastream = $object->constructDatastream($dsid, $control_group);
$datastream->label = $label;
$datastream->mimetype = $mimetype;
switch ($control_group) {
case 'M':
$datastream->setContentFromUrl($datastream_file);
break;
case 'X':
$datastream->setContentFromString(file_get_contents($datastream_file));
break;
}
$object->ingestDatastream($datastream);
}
return $object;
}

47
includes/ingest-menu.inc

@ -1,47 +0,0 @@
<?php
/**
* @file
* Menu callback functionality for islandora/ingest
*/
/**
* Callback function for islandora/ingest/%collection_pid
*
* @TODO: validate?: pid, registry return
* @param string $pid
*/
function islandora_ingest_callback($collection_object) {
if (!$collection_object) {
return drupal_not_found();
}
$ingest_registry = module_invoke_all('islandora_ingest_registry', $collection_object);
$registry_count = count($ingest_registry);
if ($registry_count == 0) {
// No ingest implementations.
drupal_set_message(t('There are no ingest methods specified for @name.', array('@name', $collection_object->label)));
drupal_goto('islandora/object/' . $collection_object->id);
}
elseif ($registry_count == 1) {
// One registry implementation, go there
drupal_goto($ingest_registry[0]['url']);
}
else {
// Multiple ingest routes registered
return islandora_ingest_registry_render($ingest_registry);
}
}
// @TODO: theme
function islandora_ingest_registry_render($ingest_registry) {
$output = array(
'#type' => 'markup',
'#markup' => '',
);
foreach ($ingest_registry AS $ingest_route) {
$output['#markup'] .= l($ingest_route['name'], $ingest_route['url']) . '<br/>';
}
return $output;
}

387
includes/ingest.form.inc

@ -0,0 +1,387 @@
<?php
/**
* @file
*
* Defines the multi-page ingest form and any relevant hooks and functions for defining the multi-page ingest forms.
*/
/**
* Ingest form build function. Initializes the form state, and builds the initial list of steps,
* excutes the current step.
*
* @param array $form
* The drupal form.
* @param array $form_state
* The drupal form state.
* @param array $configuration
* A list of key value pairs that are used to build the list of steps to be executed.
*
* @return array
* The form definition of the current step.
*/
function islandora_ingest_form(array $form, array &$form_state, array $configuration) {
islandora_ingest_form_init_form_state($form_state, $configuration);
return islandora_ingest_form_execute_step($form, $form_state);
}
/**
* Prepares/Initializes the form state for use.
*
* Also cleans up or loads any data required.
*
* @param array $form_state
* The drupal form state.
* @param array $configuration
* A list of key value pairs that are used to build the list of steps to be executed.
*/
function islandora_ingest_form_init_form_state(array &$form_state, array $configuration) {
islandora_ingest_form_init_form_state_storage($form_state, $configuration); // First time initialization of storage.
$steps = &islandora_ingest_form_get_steps($form_state);
usort($steps, 'drupal_sort_weight'); // Always re-sort the steps just incase any build/submit handlers have appended new steps.
islandora_ingest_form_step_form_load_include($form_state); // Load any required files for the current step.
}
/**
* Initializes the form_state storage for use in the ingest multi-page forms.
*
* @param array $form_state
* The drupal form state.
* @param array $configuration
* A list of key value pairs that are used to build the list of steps to be executed.
*/
function islandora_ingest_form_init_form_state_storage(array &$form_state, array $configuration) {
if (empty($form_state['islandora'])) {
$id = isset($configuration['id']) ? $configuration['id'] : NULL; // Use ID if given.
$namespace = isset($configuration['namespace']) && !isset($id) ? $configuration['namespace'] : $id; // Use namespace if ID not given.
$label = isset($configuration['label']) ? $configuration['label'] : 'New Object';
$relationship_map = function($o) { return array('relationship' => 'isMemberOfCollection', 'pid' => $o); };
$relationships = empty($configuration['collections']) ? array() : array_map($relationship_map, $configuration['collections']);
$object = islandora_prepare_new_object($namespace, $label, array(), array(), $relationships);
$form_state['islandora'] = array(
'step' => 0,
'steps' => islandora_ingest_get_steps($configuration),
'objects' => array($object),
'configuration' => $configuration
);
}
}
/**
* Executes the current step, building the form definition and appending on any additonal elements
* required for the step to function.
*
* @param array $form
* The drupal form.
* @param array $form_state
* The drupal form state.
*
* @return array
* The form definition of the current step.
*/
function islandora_ingest_form_execute_step(array $form, array &$form_state) {
$step_info = islandora_ingest_form_get_step_info($form_state);
switch ($step_info['type']) {
case 'form':
$args = array($form, &$form_state);
$args = isset($step_info['args']) ? array_merge($args, $step_info['args']) : $args;
$form = call_user_func_array($step_info['form_id'], $args);
return islandora_ingest_form_stepify($form, $form_state, $step_info);
case 'batch': // @todo Implement if possible.
break;
}
return array();
}
/**
* Append Prev/Next buttons submit/validation handlers etc.
*
* @param array $form
* The drupal form.
* @param array $form_state
* The drupal form state.
* @param array $step_info
* The info for building the current form step.
*
* @return array
* The stepified drupal form definition for the given step.
*/
function islandora_ingest_form_stepify(array $form, array &$form_state, array $step_info) {
$step = islandora_ingest_form_get_step($form_state);
$first_step = $step > 0;
$last_step = $step == (islandora_ingest_form_get_step_count($form_state) - 1);
$form['prev'] = $first_step ? islandora_ingest_form_previous_button() : NULL;
$form['next'] = $last_step ? islandora_ingest_form_ingest_button($step_info) : islandora_ingest_form_next_button($step_info);
return $form;
}
/**
* Defines the previous button for the ingest form.
*
* @return array
* The previous button for the ingest form.
*/
function islandora_ingest_form_previous_button() {
return array(
'#type' => 'submit',
'#value' => t('Previous'),
'#name' => 'prev',
'#submit' => array('islandora_ingest_form_previous_submit'),
/**
* #limit_validation_errors, is why when the previous button is pressed no values persisted in the form_state, but its also what allows us to go back when validation errors occur.
* To have a better solution going forward we can either limit validation only on required fields, or we can convert all required fields to use #element_validation functions, and
* Remove the need for #limit_validation_errors. Or maybe there is some other solution, regardless of what it is, it won't be standard.
*/
'#limit_validation_errors' => array()
);
}
/**
* The submit handler for the ingest form previous button.
*
* Stores the current form steps values in the form storage.
* Moves the focus of the multi-page ingest form back one step.
* Restores the form values for the previous step.
*
* @param array $form
* The drupal form.
* @param array $form_state
* The drupal form state.
*/
function islandora_ingest_form_previous_submit(array $form, array &$form_state) {
$step = &islandora_ingest_form_get_step($form_state);
$step_info = &islandora_ingest_form_get_step_info($form_state, $step);
$step_info['values'] = $form_state['values']; // Store values
$step--; // Goto previous step
$step_info = &islandora_ingest_form_get_step_info($form_state, $step); // Get values
$form_state['values'] = isset($step_info['values']) ? $step_info['values'] : NULL; // Use values
$form_state['rebuild'] = TRUE;
}
/**
* Defines the next button for the ingest form.
*
* Adds submit/validate handlers for the form step if they exist.
*
* @return array
* The next button for the ingest form.
*/
function islandora_ingest_form_next_button(array $step_info) {
$form_id = $step_info['form_id'];
$validate_callback = $form_id . '_validate';
$validate = function_exists($validate_callback) ? array($validate_callback) : NULL;
$submit_callback = $form_id . '_submit';
$submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_next_submit') : array('islandora_ingest_form_next_submit');
return array(
'#type' => 'submit',
'#value' => t('Next'),
'#name' => 'next',
'#validate' => $validate,
'#submit' => $submit
);
}
/**
* The submit handler for the ingest form next button.
*
* Stores the current form steps values in the form storage.
* Moves the focus of the multi-page ingest form forward one step.
* Restores the form values for the next step if present.
*
* @param array $form
* The drupal form.
* @param array $form_state
* The drupal form state.
*/
function islandora_ingest_form_next_submit(array $form, array &$form_state) {
$step = &islandora_ingest_form_get_step($form_state);
$step_info = &islandora_ingest_form_get_step_info($form_state, $step);
$step_info['values'] = $form_state['values']; // Store Values
$step++; // Goto Next Step
$step_info = &islandora_ingest_form_get_step_info($form_state, $step);
$form_state['values'] = isset($step_info['values']) ? $step_info['values'] : array(); // Restore Values if Stored.
$form_state['rebuild'] = TRUE;
}
/**
* Defines the ingest button for the ingest form.
*
* This button is only shown on the last page of the multi-page ingest form.
*
* @return array
* The ingest button for the ingest form.
*/
function islandora_ingest_form_ingest_button(array $step_info) {
$form_id = $step_info['form_id'];
$validate_callback = $form_id . '_validate';
$validate = function_exists($validate_callback) ? array($validate_callback) : NULL;
$submit_callback = $form_id . '_submit';
$submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_submit') : array('islandora_ingest_form_submit');
return array(
'#type' => 'submit',
'#name' => 'ingest',
'#value' => t('Ingest'),
'#validate' => $validate,
'#submit' => $submit
);
}
/**
* The submit handler for the ingest form.
*
* Attempts to ingest every object built by the previous steps.
*
* @param array $form
* The drupal form.
* @param array $form_state
* The drupal form state.
*/
function islandora_ingest_form_submit(array $form, array &$form_state) {
foreach ($form_state['islandora']['objects'] as $object) {
try {
islandora_add_object($object);
} catch (Exception $e) {
watchdog('islandora', $e->getMessage(), NULL, WATCHDOG_ERROR); // If post hooks throws it may already exist at this point but may be invalid, so don't say failed :P
drupal_set_message(t('A problems occured while ingesting "@label" (ID: @pid), please notifiy the administrator.', array('@label' => $object->label, '@pid' => $object->id)), 'error');
}
}
}
/**
* Gets the configuration.
*
* @param array $form_state
* The drupal form state.
*
* @return int
* The current step index.
*/
function islandora_ingest_form_get_configuration(array $form_state) {
return $form_state['islandora']['configuration'];
}
/**
* Gets the stored objects.
*
* @param array $form_state
* The drupal form state.
*
* @return int
* The current step index.
*/
function &islandora_ingest_form_get_objects(array $form_state) {
return $form_state['islandora']['objects'];
}
/**
* Gets a single object.
*
* @param array $form_state
* The drupal form state.
*
* @return int
* The current step index.
*/
function islandora_ingest_form_get_object(array $form_state) {
$objects = &islandora_ingest_form_get_objects($form_state);
return current($objects);
}
/**
* Get a reference to the current step index.
*
* @param array $form_state
* The drupal form state.
*
* @return int
* The current step index.
*/
function &islandora_ingest_form_get_step(array &$form_state) {
return $form_state['islandora']['step'];
}
/**
* Get a reference to the step info of the given step or the current step if none is given.
*
* @param array $form_state
* The drupal form state.
* @param int $step
* The index of the step to get.
*
* @return integer
* The step info of the requested step if found, NULL otherwise.
*/
function &islandora_ingest_form_get_step_info(array &$form_state, $step = NULL) {
$step = isset($step) ? $step : islandora_ingest_form_get_step($form_state);
$steps = &islandora_ingest_form_get_steps($form_state);
if (!empty($steps[$step])) {
return $steps[$step];
}
return NULL; // @todo deal with unknown case.
}
/**
* Get a reference to the steps stored in the form state.
*
* @param array $form_state
* The drupal form state.
*
* @return array
* All the steps to be used in the ingest process.
*/
function &islandora_ingest_form_get_steps(array &$form_state) {
return $form_state['islandora']['steps'];
}
/**
* Call form_load_include, for the current step if it defines a required file.
*
* @param array $form_state
* The drupal form state.
*/
function islandora_ingest_form_step_form_load_include(array &$form_state) {
form_load_include($form_state, 'inc', 'islandora', 'includes/ingest.form'); // Always load this file.
$step_info = islandora_ingest_form_get_step_info($form_state);
if (isset($step_info['file']) && isset($step_info['module'])) {
$matches = array();
preg_match('/^(.*)\.(.*)$/', $step_info['file'], $matches);
list($file, $name, $type) = $matches;
form_load_include($form_state, $type, $step_info['module'], $name); // Load include files.
}
}
/**
* Get the number of steps.
*
* @param array $form_state
* The drupal form state.
*
* @return int
* The number of steps.
*/
function islandora_ingest_form_get_step_count(array $form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
return count($steps);
}
/**
* Buildes the initial list of ingest steps. Sorted by weight expected range between -50 to 50.
*
* The sort order is undefined for steps which have the same weight.
*
* @param array $configuration
* The configuration options used to build the multi-paged ingest process.
*
* @return array
* The initial list of sorted ingest steps as defined by all implementers of ISLANDORA_INGEST_STEP_HOOK.
*/
function islandora_ingest_get_steps(array $configuration) {
module_load_include('inc', 'islandora', 'includes/utilities');
$steps = array();
$models = isset($configuration['models']) ? $configuration['models'] : array();
foreach (islandora_build_hook_list(ISLANDORA_INGEST_STEP_HOOK, $models) as $hook) {
$steps = array_merge($steps, module_invoke_all($hook, $configuration));
}
usort($steps, 'drupal_sort_weight');
return $steps;
}

62
includes/ingest.menu.inc

@ -0,0 +1,62 @@
<?php
/**
* @file
*
* Ingest Menu callback hooks.
*/
/**
* Menu callback, Renders the multi-page ingest form if possible.
*
* @return string
* HTML representing the mult-page ingest form.
*/
function islandora_ingest_callback() {
$configuration = islandora_ingest_get_configuration();
if ($configuration === FALSE) { // Redirect back to referer or top level collection.
drupal_set_message(t('Invalid ingest configuration.'), 'error');
$redirect = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '<front>';
drupal_goto($redirect);
}
module_load_include('inc', 'islandora', 'includes/ingest.form');
return drupal_get_form('islandora_ingest_form', $configuration);
}
/**
* Fetches/validates the ingest configuration from the $_GET parameters.
*
* Generic parameters as accepted by all ingest processes, other modules may add to this list.
* id -> The pid of the object to create. optional.
* models -> Comma delimited list of all the content models the created object should have.
* collections -> Comma delimited list of all the collections the created object should belong to.
*
* @return array
* The configuration options used to build the multi-paged ingest process.
*/
function islandora_ingest_get_configuration() {
$configuration = $_GET;
unset($configuration['q']);
$convert_to_array_keys = array_intersect(array('models', 'collections'), array_keys($configuration));
foreach ($convert_to_array_keys as $key) {
$configuration[$key] = explode(',', $configuration[$key]);
}
// @todo add hook for manipulating/validating the configuration.
return islandora_valid_ingest_configuration($configuration) ? $configuration : FALSE;
}
/**
* Validates the given ingest configuration.
*
* At the moment it requires that models and collections are present.
*
* @param array $configuration
* The key value pairs that are used to build the multi-paged ingest process.
*
* @return boolean
* TRUE if the configuration is valid, FALSE otherwise.
*/
function islandora_valid_ingest_configuration(array $configuration) {
// @todo Add more robust validation, add watchdog logs, etc.
return isset($configuration['models']) && isset($configuration['collections']);
}

235
includes/islandora.ingest.inc

@ -1,235 +0,0 @@
<?php
/**
* @file
* This file contains ingest callback functions.
*/
/**
* @TODO: needs documentation
*/
function islandora_ingest_get_information(AbstractFedoraObject $collection_object) {
$models = $collection_object->models;
$collection_info = module_invoke_all('islandora_ingest_get_information', $models, $collection_object);
return $collection_info;
}
/**
* Get an ingestable object.
*
* @deprecated
* Deprecated in favour of the more flexible
* islandora_ingest_new_object_prepare()--which this function has been made
* to call behind the scenes anyway.
*
* @param array $content_models
* An array of content models to which the new object should subscribe, where
* each content model is described by an associative array containing:
* - pid: The Fedora PID of the content model.
* @param string $collection_pid
* The collection to which the new object should belong.
* @param string $relationship
* The relationship this object will have to the collection.
* @param string $namespace
* The namespace in which the PID for the new object will be created.
*
* @return NewFedoraObject
* A NewFedoraObject which may be adjusted before ingesting.
*/
function islandora_ingest_get_object($content_models, $collection_pid, $relationship, $namespace) {
$models = array();
foreach ($content_models as $relation) {
$models[] = $relation['pid'];
}
return islandora_ingest_new_object_prepare($namespace, NULL, array(), $models, array(
array(
'pid' => $collection_pid,
'relationship' => $relationship,
),
), $collection_pid);
}
/**
* Prepare an ingestable object.
*
* @param string $namespace
* The namespace in which the PID for the new object will be created.
* @param string $label
* An optional label to apply to the object.
* @param array $datastreams
* A array of datastreams to add, where each datastream definition is an
* associative array containing:
* - dsid: The datastream ID.
* - label: An optional label for the datastream.
* - mimetype: A MIMEtype for the datastream; defaults to text/xml.
* - control_group: One of X, M, R and E; defaults to M.
* - datastream_file: A web-accessible path, for which we try to get an
* absolute path using url().
* @param array $content_models
* An array of content model PIDs to which the new object should subscribe.
* @param array $relationships
* An array of relationships, where each relationship is an associative array
* containing:
* - relationship: The predicate for the relationship, from the Fedora
* RELS-EXT namespace.
* - pid: The object for the relationship, to which we are creating the
* relationhsip.
*
* @return NewFedoraObject
* An ingestable NewFedoraObject.
*/
function islandora_ingest_new_object_prepare($namespace = NULL, $label = NULL, $datastreams = array(), $content_models = array(), $relationships = array(), $collection_pid = NULL) {
// include Tuque library
module_load_include('inc', 'islandora', 'includes/tuque');
global $user;
// new connection
try {
$connection = new IslandoraTuque($user);
} catch (Exception $e) {
drupal_set_message(t('Unable to connect to the repository %e', array('%e' => $e)), 'error');
return;
}
// construct new object
$object = $connection->repository->constructObject($namespace);
// add label
if (!empty($label)) {
$object->label = $label;
}
// add content model relationship(s)
foreach ($content_models as $content_model) {
$object->relationships->add(FEDORA_MODEL_URI, 'hasModel', $content_model);
}
// add collection relationship(s)
if (!empty($relationships)) {
foreach ($relationships as $relationship) {
$object->relationships->add(FEDORA_RELS_EXT_URI, $relationship['relationship'], $relationship['pid']);
}
}
// add datastreams
foreach ((array) $datastreams as $ds) {
// variables
$ds_id = $ds['dsid'];
$ds_label = isset($ds['label']) ? $ds['label'] : '';
$ds_mimetype = isset($ds['mimetype']) ? $ds['mimetype'] : 'text/xml';
$ds_control_group = (isset($ds['control_group']) AND in_array($ds['control_group'], array('X', 'M', 'R', 'E'))) ? $ds['control_group'] : 'M';
$ds_datastream_file = url($ds['datastream_file'], array('absolute' => TRUE));
// datastream object
$datastream = $object->constructDatastream($ds_id, $ds_control_group);
$datastream->label = $ds_label;
$datastream->mimetype = $ds_mimetype;
switch ($ds_control_group) {
case 'M':
$datastream->setContentFromUrl($ds_datastream_file);
break;
case 'X':
$datastream->setContentFromString(file_get_contents($ds_datastream_file));
break;
}
$object->ingestDatastream($datastream);
}
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list('islandora_ingest_pre_ingest', $content_models) as $hook) {
module_invoke_all($hook, $object, $content_models, $collection_pid);
}
return $object;
}
/**
* Ingest the given object into Fedora.
*
* @param NewFedoraObject $object
* An ingestable FedoraObject.
*
* @return FedoraObject
* The ingested FedoraObject, after running the post ingest hooks.
*/
function islandora_ingest_add_object(&$object) {
$object->repository->ingestObject($object);
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_POST_INGEST_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object);
}
return $object;
}
/**
* Ingest an object.
*
* @param array $object_model
* An associative array containing the necessary parameters to create the
* desired object:
* - pid: The PID with which the object will be created.
* - label: An optional label to apply to the object.
* - datastreams: Same as the "datastreams" array accepted by
* islandora_ingest_new_object_prepare().
* - cmodel: Either an array of content models as accepted by
* islandora_ingest_new_object_prepare(), or a single content model PID to add
* to the object.
* - parent: Either an array of parents, or a single parent PID to which to
* relate to; uses isMemberOfCollection by default.
* - relationships: An array of relationships as accepted by
* islandora_ingest_new_object_prepare().
*
* @return FedoraObject
* An FedoraObject which has been ingested into Fedora.
*/
function islandora_ingest_new_object($object_model) {
// prepare variables
// namespace
$namespace = $object_model['pid'];
// label
$label = !empty($object_model['label']) ? $object_model['label'] : NULL;
// datastreams
$datastreams = array();
if (!empty($object_model['datastreams']) AND is_array($object_model['datastreams'])) {
$datastreams = $object_model['datastreams'];
}
// content models
$content_models = array();
if (!empty($object_model['cmodel'])) {
if (is_array($object_model['cmodel'])) {
$content_models = $object_model['cmodel'];
}
else {
$content_models[] = $object_model['cmodel'];
}
}
// relationships
$relationships = array();
// single parent
if (!empty($object_model['parent']) AND !is_array($object_model['parent'])) {
$relationships[] = array('relationship' => 'isMemberOfCollection', 'pid' => $object_model['parent']);
}
// parents array
if (!empty($object_model['parents']) AND is_array($object_model['parents'])) {
foreach ($object_model['parents'] as $parent) {
$relationships[] = array('relationship' => 'isMemberOfCollection', 'pid' => $parent);
}
}
// other relationships
if (!empty($object_model['relationships']) AND is_array($object_model['relationships'])) {
foreach ($object_model['relationships'] as $relationship) {
$relationships[] = array('relationship' => $relationship['relationship'], 'pid' => $relationship['pid']);
}
}
// build new object
$object = islandora_ingest_new_object_prepare($namespace, $label, $datastreams, $content_models, $relationships);
// ingest (and return) new object
return islandora_ingest_add_object($object);
}

116
includes/object_properties.form.inc

@ -0,0 +1,116 @@
<?php
/**
* @file
*
* Contains admin form functions for editing an object's properties.
*/
/**
* Object properties admin form.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraObject $object
* The object whose properties this form will modify.
*
* @return array
* The drupal form definition.
*/
function islandora_object_properties_form(array $form, array &$form_state, FedoraObject $object) {
drupal_set_title($object->label);
$form_state['object'] = $object;
return array(
'pid' => array(
'#type' => 'hidden',
'#value' => $object->id
),
'object_label' => array(
'#title' => t('Item Label'),
'#default_value' => $object->label,
'#required' => 'TRUE',
'#description' => t('A Human readable label'),
'#size' => 120, // Double the normal length
'#maxlength' => 255, // Max length for a Fedora Label
'#type' => 'textfield'
),
'object_owner' => array( // @todo Make this into an autocomplete field that list the users in the system as well.
'#title' => t('Owner'),
'#default_value' => $object->owner,
'#required' => FALSE,
'#description' => t('The owner id'),
'#type' => 'textfield'
),
'object_state' => array(
'#title' => t('State'),
'#default_value' => $object->state,
'#required' => TRUE,
'#description' => t('The items state one of active, inactive or deleted'),
'#type' => 'select',
'#options' => array('A' => 'Active', 'I' => 'Inactive', 'D' => 'Deleted')
),
'submit' => array(
'#type' => 'submit',
'#value' => 'Update Properties'
),
'delete' => array(
'#type' => 'submit',
'#value' => t('Delete'),
'#submit' => array('islandora_object_properties_form_delete'),
'#limit_validation_errors' => array(array('pid'))
)
);
}
/**
* Submit handler for object properties admin form.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_object_properties_form_submit(array $form, array &$form_state) {
$object = $form_state['object'];
$owner = $form_state['values']['object_owner'];
$state = $form_state['values']['object_state'];
$label = $form_state['values']['object_label'];
if (isset($owner) && $owner != $object->owner) {
try {
$object->owner = $owner;
drupal_set_message(t('Successfully updated owner %s', array('%s' => $owner)));
} catch (Exception $e) {
form_set_error('object_owner', t('Error updating owner %s', array('%s' => $e->getMessage())));
}
}
if (isset($state) && $state != $object->state) {
try {
$object->state = $state;
drupal_set_message(t('Successfully updated state %s', array('%s' => $state)));
} catch (Exception $e) {
form_set_error('object_state', t('Error updating state %s', array('%s' => $e->getMessage())));
}
}
if (isset($label) && $label != $object->label) {
try {
$object->label = $label;
drupal_set_message(t('Successfully updated label %s', array('%s' => check_plain($label))));
} catch (Exception $e) {
form_set_error(t('Error updating label %s', array('%s' => $e->getMessage())));
}
}
}
/**
* Callback function for object properties admin form delete button.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_object_properties_form_delete(array $form, array &$form_state) {
drupal_goto("islandora/object/{$form_state['values']['pid']}/delete");
}

125
includes/object_properties.inc

@ -1,125 +0,0 @@
<?php
/**
* @file
* Contains admin form functions for object properties
*/
/**
* Validate function for object properties admin form.
*
* @TODO: may want more validation here the only restrictions i see on
* the object label and owner is the foxml schema says they should be
* an xsd:string there maybe further restrictions such as length but they aren't
* defined in the schema.
* @param array $form
* @param array $form_state
* @return boolean
*/
function islandora_edit_properties_form_validate($form, &$form_state) {
$islandora_object = islandora_object_load($form_state['values']['pid']);
if (!isset($islandora_object)) {
form_set_error('', t('Could not update properties object not found.'));
return FALSE;
}
}
/**
* Submit function for object properties admin form.
*
* @param array $form
* @param array $form_state
*/
function islandora_edit_properties_form_submit($form, &$form_state) {
$islandora_object = islandora_object_load($form_state['values']['pid']);
$owner = $form_state['values']['object_owner'];
$state = $form_state['values']['object_state'];
$label = $form_state['values']['object_label'];
if (isset($owner) && $owner != $islandora_object->owner) {
try {
$islandora_object->owner = $owner;
drupal_set_message(t('Successfully updated owner %s', array('%s' => $owner)));
} catch (Exception $e) {
form_set_error('object_owner', t('Error updating owner %s', array('%s' => $e->getMessage())));
}
}
if (isset($state) && $state != $islandora_object->state) {
try {
$islandora_object->state = $state;
drupal_set_message(t('Successfully updated state %s', array('%s' => $state)));
} catch (Exception $e) {
form_set_error('object_state', t('Error updating state %s', array('%s' => $e->getMessage())));
}
}
if (isset($label) && $label != $islandora_object->label) {
try {
$islandora_object->label = $label;
drupal_set_message(t('Successfully updated label %s', array('%s' => check_plain($label))));
} catch (Exception $e) {
form_set_error(t('Error updating label %s', array('%s' => $e->getMessage())));
}
}
}
/**
* Callback function for object properties admin form delete button.
*/
function islandora_edit_properties_form_delete($form, &$form_state) {
$islandora_object = $form_state['values']['pid'];
drupal_goto("islandora/object/$islandora_object/delete");
}
/**
* Object properties admin form.
*
* @param array $form
* @param array $form_state
* @param string $object_id
* an object id
* @return array
*/
function islandora_edit_properties_form($form, &$form_state, $object) {
$form = array();
if (!isset($object)) {
return NULL;
}
drupal_set_title($object->label);
$form['pid'] = array(
'#type' => 'hidden',
'#value' => $object->id,
);
$form['object_label'] = array(
'#title' => t('Item Label'),
'#default_value' => $object->label,
'#required' => 'TRUE',
'#description' => t('A Human readable label'),
'#type' => 'textfield'
);
$form['object_owner'] = array(
'#title' => t('Owner'),
'#default_value' => $object->owner,
'#required' => FALSE,
'#description' => t('The owner id'),
'#type' => 'textfield',
);
$form['object_state'] = array(
'#title' => t('State'),
'#default_value' => $object->state,
'#required' => TRUE,
'#description' => t('The items state one of active, inactive or deleted'),
'#type' => 'select',
'#options' => array('A' => 'Active', 'I' => 'Inactive', 'D' => 'Deleted'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Update Properties',
);
$form['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#submit' => array('islandora_edit_properties_form_delete'),
'#limit_validation_errors' => array(array('pid')),
);
return $form;
}

138
includes/purge.form.inc

@ -1,138 +0,0 @@
<?php
/**
* @file
* This file contains the admin (confirmation) form and callback functions to purge an object.
*/
/**
* Gives the option of deleting or purging and object.
*
* The default behaviour is to purge the object to reduce maintenance.
* If a solution pack wants to change this behaviour and have the object set to deleted then
* it can respond to the 'islandora_pre_purge_object' hook with an array containing the pair
* 'delete' => TRUE.
* Once the object has been deleted/purged then a second call lets the solution packs know that
* the object has been dealt with. In this call the object id and content models are sent out so
* that the solution packs can act on this news. There is no guarantee that the object still exists
* and so the object object isn't sent.
*
* @param string $object_id
* ID of the object
* @return type
*/
function islandora_purge_object_submit($form, &$form_state) {
$object_id = $form_state['values']['pid'];
$collection = $form_state['values']['col'];
// purge object
islandora_object_purge($object_id);
drupal_goto($collection);
}
function islandora_purge_object($form, &$form_state, $object) {
module_load_include('inc', 'islandora', 'includes/datastream');
$parent = islandora_datastream_get_parents($object);
$key = array_keys($parent);
if (count($key) > 0) {
$redirect = "islandora/object/$key[0]";
}
else {
$redirect = "islandora";
}
$form['pid'] = array('#type' => 'value', '#value' => $object->id);
$form['col'] = array('#type' => 'value', '#value' => $redirect);
return confirm_form($form,
t('Are you sure you want to delete %title?', array('%title' => $object->label)),
"islandora/object/$object->id",
t('This action cannot be undone.'),
t('Delete'),
t('Cancel')
);
}
function islandora_purge_datastream($form, &$form_state, $object, $datastream_id) {
module_load_include('inc', 'islandora', 'includes/datastream');
$datastream = $object->getDatastream($datastream_id);
$redirect = "islandora/object/$object->id";
$form['pid'] = array('#type' => 'value', '#value' => $object->id);
$form['dsid'] = array('#type' => 'value', '#value' => $datastream_id);
$form['col'] = array('#type' => 'value', '#value' => $redirect);
return confirm_form($form,
t('Are you sure you want to delete the %dsid datastream?', array('%dsid' => $datastream->id)),
"islandora/object/$object->id",
t('This action cannot be undone.'),
t('Delete'),
t('Cancel')
);
}
/**
* Gives the option of purging or deleting a datastream.
*
* The default behaviour is to purge the datastream but this can be overridden using the
* 'islandora_pre_purge_datastream' hook. The returned array can include a 'block' => TRUE
* pair which will prevent the datastream from being deleted if it particularly needed for
* a certain function. Returning 'delete' => TRUE will cause the datastream to be put into
* a deleted state.
*
* @param string $object_id
* ID of the object
* @param string $datastream_id
* ID of the datastream
*
*/
function islandora_purge_datastream_submit($form, &$form_state) {
$object_id = $form_state['values']['pid'];
$datastream_id = $form_state['values']['dsid'];
if (!isset($datastream_id)) {
drupal_set_message(t('Cannot remove datastream, datastream id not set'));
return;
}
$object = islandora_object_load($object_id);
if (!isset($object)) {
drupal_set_message(t('Could not remove object, object not found'));
return;
}
//notify modules of pending deletion so we can update rels etc
$arr = module_invoke_all('islandora_pre_purge_datastream', $object[$datastream_id]);
if (isset($arr['block']) && $arr['block']) {
drupal_set_message(t('Purging of the %d datastream was blocked', array('%d' => $datastream_id)), 'warning');
return;
}
if (isset($arr['delete']) && $arr['delete']) {
try {
$object[$datastream_id]->state = 'D';
} catch (Exception $e) {
drupal_set_message(t('Error deleting %s datastream from Islandora object %o %e', array('%s' => $datastream_id, '%o' => $object->id, '%e' => $e)), 'error');
return;
}
}
else {
try {
$object->purgeDatastream($datastream_id);
} catch (Exception $e) {
drupal_set_message(t('Error purging %s datastream from Islandora object %o %e', array('%s' => $datastream_id, '%o' => $object_id, '%e' => $e)), 'error');
return;
}
}
//notify modules post deletion
module_invoke_all('islandora_post_purge_datastream', $object, $datastream_id);
drupal_set_message(t('%d datastream sucessfully purged from Islandora object %o', array('%d' => $datastream_id, '%o' => $object->label)));
drupal_goto('islandora/object/' . $object->id);
}

153
includes/solution_packs.inc

@ -2,29 +2,24 @@
/** /**
* @file * @file
*
* This file contains all admin and callback functions for solution pack management. * This file contains all admin and callback functions for solution pack management.
*/ */
/** /**
* Solution pack admin page callback * Solution pack admin page callback.
*/ */
function islandora_solution_packs_admin() { function islandora_solution_packs_admin() {
// add css
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
// check connection
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora'); drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
$info = islandora_describe_repository($url); if (!islandora_describe_repository()) {
if (!$info) { $message = t('Could not connect to the repository. Please check the settings on the ' .
$config_url = url('admin/islandora/configure'); '<a href="@config_url" title="Islandora configuration page">Islandora configuration</a> page.',
drupal_set_message(t('Could not connect to the repository. Please check the settings on the <a href="@config_url" title="Islandora configuration page">Islandora configuration</a> page.', array('@config_url' => $config_url)), 'error'); array('@config_url' => url('admin/islandora/configure')));
drupal_set_message($message, 'error');
} }
// set variables
$enabled_solution_packs = module_invoke_all('islandora_required_objects'); $enabled_solution_packs = module_invoke_all('islandora_required_objects');
$output = ''; $output = '';
foreach ($enabled_solution_packs as $solution_pack_module => $solution_pack_info) { foreach ($enabled_solution_packs as $solution_pack_module => $solution_pack_info) {
$objects = array(); $objects = array();
foreach ($solution_pack_info as $field => $value) { foreach ($solution_pack_info as $field => $value) {
@ -37,12 +32,9 @@ function islandora_solution_packs_admin() {
break; break;
} }
} }
// get form
$form_array = drupal_get_form('islandora_solution_pack_form_' . $solution_pack_module, $solution_pack_module, $solution_pack_name, $objects); $form_array = drupal_get_form('islandora_solution_pack_form_' . $solution_pack_module, $solution_pack_module, $solution_pack_name, $objects);
// render form
$output .= drupal_render($form_array); $output .= drupal_render($form_array);
} }
return $output; return $output;
} }
@ -50,10 +42,7 @@ function islandora_solution_packs_admin() {
* Solution pack admin page * Solution pack admin page
*/ */
function islandora_solution_pack_form($form, &$form_state, $solution_pack_module, $solution_pack_name, $objects = array()) { function islandora_solution_pack_form($form, &$form_state, $solution_pack_module, $solution_pack_name, $objects = array()) {
// set variables
global $base_url; global $base_url;
global $base_path;
$needs_update = FALSE; $needs_update = FALSE;
$needs_install = FALSE; $needs_install = FALSE;
$could_not_connect = FALSE; $could_not_connect = FALSE;
@ -120,8 +109,6 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
$could_not_connect = TRUE; $could_not_connect = TRUE;
break; break;
} }
// label
if ($needs_install OR $could_not_connect) { if ($needs_install OR $could_not_connect) {
$label = $object['label'] ? $object['label'] : ''; $label = $object['label'] ? $object['label'] : '';
} }
@ -129,11 +116,8 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
$label = $object['label'] ? l($object['label'], $base_url . '/islandora/object/' . $pid) : ''; $label = $object['label'] ? l($object['label'], $base_url . '/islandora/object/' . $pid) : '';
} }
$table_row[] = $label; $table_row[] = $label;
// pid
$table_row[] = $pid; $table_row[] = $pid;
// object status
$table_row[] = $object_status; $table_row[] = $object_status;
// add row
$table_rows[] = $table_row; $table_rows[] = $table_row;
} }
} }
@ -169,14 +153,12 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
$submit_button_text = ''; $submit_button_text = '';
} }
// table
$form['solution_pack']['table'] = array( $form['solution_pack']['table'] = array(
'#type' => 'item', '#type' => 'item',
'#markup' => theme('table', array('header' => $table_header, 'rows' => $table_rows)), '#markup' => theme('table', array('header' => $table_header, 'rows' => $table_rows)),
); );
} }
// submit
if (!$could_not_connect) { if (!$could_not_connect) {
$form['solution_pack']['submit'] = array( $form['solution_pack']['submit'] = array(
'#value' => $submit_button_text, '#value' => $submit_button_text,
@ -185,12 +167,8 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
'#attributes' => array('class' => array('islandora-solution-pack-submit')), '#attributes' => array('class' => array('islandora-solution-pack-submit')),
'#weight' => 40, '#weight' => 40,
); );
// submit callback $form['solution_pack']['#submit'] = array('islandora_solution_pack_form_submit');
$form['solution_pack']['#submit'] = array(
'islandora_solution_pack_form_submit',
);
} }
return $form; return $form;
} }
@ -203,8 +181,6 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
* The state of the form submited. * The state of the form submited.
*/ */
function islandora_solution_pack_form_submit($form, &$form_state) { function islandora_solution_pack_form_submit($form, &$form_state) {
// get variables
$solution_pack_module = $form_state['values']['solution_pack_module']; $solution_pack_module = $form_state['values']['solution_pack_module'];
$solution_pack_name = $form_state['values']['solution_pack_name']; $solution_pack_name = $form_state['values']['solution_pack_name'];
$objects = $form_state['values']['objects']; $objects = $form_state['values']['objects'];
@ -228,22 +204,16 @@ function islandora_solution_pack_form_submit($form, &$form_state) {
} }
/** /**
* Batch reingest object(s) * Batch reingest object(s)
* *
* @param type $object * @param array $object
* @param type $context * @param type $context
* @return type * @return type
*/ */
function islandora_batch_reingest_object($object_model, &$context) { function islandora_batch_reingest_object($object_model, &$context) {
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('inc', 'islandora', 'includes/islandora.ingest');
// include Tuque library
module_load_include('inc', 'islandora', 'includes/tuque');
global $user; global $user;
global $base_url; global $base_url;
// new connection // new connection
@ -256,9 +226,8 @@ function islandora_batch_reingest_object($object_model, &$context) {
} }
if (!empty($object_model) && is_array($object_model)) { if (!empty($object_model) && is_array($object_model)) {
// set and validate PID
$pid = $object_model['pid']; $pid = $object_model['pid'];
if (!islandora_validate_pid($pid)) { if (!islandora_is_valid_pid($pid)) {
return NULL; return NULL;
} }
@ -267,13 +236,16 @@ function islandora_batch_reingest_object($object_model, &$context) {
$object_query = $connection->api->a->findObjects('query', 'pid=' . $pid); $object_query = $connection->api->a->findObjects('query', 'pid=' . $pid);
$reinstall = FALSE; $reinstall = FALSE;
if (!empty($object_query['results'])) { if (!empty($object_query['results'])) {
islandora_object_purge($pid); $object = islandora_get_object_by_id($pid);
if (isset($object)) {
islandora_delete_object($object);
}
$reinstall = TRUE; $reinstall = TRUE;
} }
// build and ingest new object // build and ingest new object
try { try {
$object = islandora_ingest_new_object($object_model); $object = islandora_solution_pack_add_object($object_model);
$object_name = $object->label; $object_name = $object->label;
if ($reinstall) { if ($reinstall) {
drupal_set_message(t('Successfully reinstalled <em>@object_name</em>.', array('@object_name' => $object_name, '@pid' => $pid))); drupal_set_message(t('Successfully reinstalled <em>@object_name</em>.', array('@object_name' => $object_name, '@pid' => $pid)));
@ -299,9 +271,7 @@ function islandora_install_solution_pack($module_name = NULL, $op = 'install') {
if (!empty($module_name)) { if (!empty($module_name)) {
// include files // include files
module_load_include('inc', 'islandora', 'includes/tuque');
module_load_include('module', 'islandora', 'islandora'); module_load_include('module', 'islandora', 'islandora');
module_load_include('inc', 'islandora', 'includes/islandora.ingest');
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('module', $module_name, $module_name); module_load_include('module', $module_name, $module_name);
@ -381,9 +351,7 @@ function islandora_install_solution_pack($module_name = NULL, $op = 'install') {
} }
} }
else { else {
// build and ingest new object islandora_solution_pack_add_object($object);
islandora_ingest_new_object($object);
// set message
drupal_set_message(st('@module_label: installed <a href="@object_url" title="@pid">@label</a> object.', array('@module_label' => $module_label, '@label' => $label, '@pid' => $pid, '@object_url' => $object_url))); drupal_set_message(st('@module_label: installed <a href="@object_url" title="@pid">@label</a> object.', array('@module_label' => $module_label, '@label' => $label, '@pid' => $pid, '@object_url' => $object_url)));
} }
break; break;
@ -485,6 +453,87 @@ function islandora_check_object_status($object_model = array()) {
} }
} }
/**
* Converts the given definition into an object and add's it to the repository.
*
* @param array $object_definition
* An associative array containing the necessary parameters to create the
* desired object:
* - pid: The PID with which the object will be created.
* - label: An optional label to apply to the object.
* - datastreams: Same as the "datastreams" array accepted by
* islandora_prepare_new_object().
* - cmodel: Either an array of content models as accepted by
* islandora_preprare_new_object(), or a single content model PID to add
* to the object.
* - parent: Either an array of parents, or a single parent PID to which to
* relate to; uses isMemberOfCollection by default.
* - relationships: An array of relationships as accepted by
* islandora_prepare_new_object().
*
* @return FedoraObject
* The newly created object.
*/
function islandora_solution_pack_add_object(array $object_definition) {
$object = islandora_solution_pack_prepare_new_object($object_definition);
return islandora_add_object($object);
}
/**
* Prepares a new object based on the solution pack style of declaring them as arrays.
*
* @param array $object_definition
* An associative array containing the necessary parameters to create the
* desired object:
* - pid: The PID with which the object will be created.
* - label: An optional label to apply to the object.
* - datastreams: Same as the "datastreams" array accepted by
* islandora_prepare_new_object().
* - cmodel: Either an array of content models as accepted by
* islandora_prepare_new_object(), or a single content model PID to add
* to the object.
* - parent: Either an array of parents, or a single parent PID to which to
* relate to; uses isMemberOfCollection by default.
* - relationships: An array of relationships as accepted by
* islandora_prepare_new_object().
*
* @return NewFedoraObject
* An NewFedoraObject which has been initalized with the given properties.
*/
function islandora_solution_pack_prepare_new_object(array $object_definition) {
$namespace = $object_definition['pid'];
$label = !empty($object_definition['label']) ? $object_definition['label'] : NULL;
$datastreams = array();
if (!empty($object_definition['datastreams']) AND is_array($object_definition['datastreams'])) {
$datastreams = $object_definition['datastreams'];
}
$content_models = array();
if (!empty($object_definition['cmodel'])) {
if (is_array($object_definition['cmodel'])) {
$content_models = $object_definition['cmodel'];
}
else {
$content_models[] = $object_definition['cmodel'];
}
}
$relationships = array();
if (!empty($object_definition['parent']) AND !is_array($object_definition['parent'])) {
$relationships[] = array('relationship' => 'isMemberOfCollection', 'pid' => $object_definition['parent']);
}
if (!empty($object_definition['parents']) AND is_array($object_definition['parents'])) {
foreach ($object_definition['parents'] as $parent) {
$relationships[] = array('relationship' => 'isMemberOfCollection', 'pid' => $parent);
}
}
if (!empty($object_definition['relationships']) AND is_array($object_definition['relationships'])) {
foreach ($object_definition['relationships'] as $relationship) {
$relationships[] = array('relationship' => $relationship['relationship'], 'pid' => $relationship['pid']);
}
}
return islandora_prepare_new_object($namespace, $label, $datastreams, $content_models, $relationships);
}
/** /**
* @defgroup viewer-functions * @defgroup viewer-functions
* @{ * @{
@ -591,7 +640,7 @@ function islandora_get_viewers($mimetype = NULL) {
// get all viewers // get all viewers
$defined_viewers = module_invoke_all('islandora_viewer_info'); $defined_viewers = module_invoke_all('islandora_viewer_info');
// filter viewers by mimetype // filter viewers by mimetype
foreach($defined_viewers as $key => $value) { foreach ($defined_viewers as $key => $value) {
if (in_array($mimetype, $value['mimetype']) OR $mimetype == NULL) { if (in_array($mimetype, $value['mimetype']) OR $mimetype == NULL) {
$viewers[$key] = $value; $viewers[$key] = $value;
} }
@ -702,10 +751,8 @@ function islandora_get_viewer_id($variable_id) {
*/ */
function islandora_get_viewer_callback($viewer_id = NULL) { function islandora_get_viewer_callback($viewer_id = NULL) {
if ($viewer_id !== NULL) { if ($viewer_id !== NULL) {
// get defined viewers
$viewers = module_invoke_all('islandora_viewer_info'); $viewers = module_invoke_all('islandora_viewer_info');
if (isset($viewers[$viewer_id]['callback'])) { if (isset($viewers[$viewer_id]['callback'])) {
// return callback function
return $viewers[$viewer_id]['callback']; return $viewers[$viewer_id]['callback'];
} }
} }

85
includes/utilities.inc

@ -58,45 +58,43 @@ function islandora_control_group_to_human_readable($control_group) {
} }
/** /**
* valid pid ?? * Checks if the given pid is valid.
* @param type $pid *
* @param string $pid
* The object id to check.
*
* @return boolean * @return boolean
* TRUE if valid, FALSE otherwise.
*/ */
function islandora_validate_pid($pid) { function islandora_is_valid_pid($pid) {
$valid = FALSE; return drupal_strlen(trim($pid)) <= 64 && preg_match('/^([A-Za-z0-9]|-|\.)+:(([A-Za-z0-9])|-|\.|~|_|(%[0-9A-F]{2}))+$/', trim($pid));
if (drupal_strlen(trim($pid)) <= 64 && preg_match('/^([A-Za-z0-9]|-|\.)+:(([A-Za-z0-9])|-|\.|~|_|(%[0-9A-F]{2}))+$/', trim($pid))) {
$valid = TRUE;
}
return $valid;
} }
/** /**
* Valid Dsid ?? * Checks if the given datastream id is valid.
* @param type $dsid *
* @param string $dsid
* The datastream id to check.
*
* @return boolean * @return boolean
* TRUE if valid, FALSE otherwise.
*/ */
function islandora_validate_dsid($dsid) { function islandora_is_valid_dsid($dsid) {
$valid = FALSE; return drupal_strlen(trim($dsid)) <= 64 && preg_match('/^[a-zA-Z0-9\_\-\.]+$/', trim($dsid));
if (drupal_strlen(trim($dsid)) <= 64 && preg_match('/^[a-zA-Z0-9\_\-\.]+$/', trim($dsid))) {
$valid = TRUE;
}
return $valid;
} }
/* Helper function to describe a Fedora repository. /* Helper function to describe a Fedora repository.
* *
* Can be used to check if Fedora is available. * Can be used to check if Fedora is available.
* *
* @param $url * @param string $url
* A url to a Fedora repository. * A url to a Fedora repository, if NULL the default is used.
* @return * @return
* Returns an array describing the repository. Returns FALSE if Fedora is down * Returns an array describing the repository. Returns FALSE if Fedora is down
* or if the url is incorrect. * or if the url is incorrect.
*/ */
function islandora_describe_repository($url) { function islandora_describe_repository($url = NULL) {
module_load_include('inc', 'islandora', 'includes/tuque'); $url = isset($url) ? $url : variable_get('islandora_base_url', 'http://localhost:8080/fedora');
$connection = new IslandoraTuque(NULL, $url); $connection = new IslandoraTuque(NULL, $url);
try { try {
$info = $connection->api->a->describeRepository(); $info = $connection->api->a->describeRepository();
@ -152,3 +150,46 @@ function islandora_escape_pid_for_function($pid) {
$pid $pid
); );
} }
/**
* Gets the namespace of the given id.
*
* @param string $id
* Either a PID or namespace to check for accessibility. Any string like those below are fine.
* @code
* 'islandora',
* 'islandora:',
* 'islandora:1234',
* @endcode
*
* @return string
* The namespace portion of the given string.
*/
function islandora_get_namespace($id) {
$matches = array();
preg_match('/^([^:]*)/', $id, $matches);
return $matches[0];
}
/**
* Checks the given namespace or PID is/has an accessible namespace as defined by the "islandora_pids_allowed" variable.
*
* @param string $namespace
* Either a PID or namespace to check for accessibility. Any string like those below are fine.
* @code
* 'islandora',
* 'islandora:',
* 'islandora:1234',
* @endcode
*
* @return boolean
* TRUE if accessible, FALSE otherwise.
*/
function islanodra_namespace_accessible($id) {
if (variable_get('islandora_namespace_restriction_enforced', FALSE)) {
$namespace = islandora_get_namespace($id) . ':';
$allowed_namespaces = explode(" ", variable_get('islandora_pids_allowed', 'default: demo: changeme: islandora: ilives: islandora-book: books: newspapers: '));
return in_array($namespace, $allowed_namespaces);
}
return TRUE;
}

12
islandora.api.php

@ -155,17 +155,15 @@ function hook_islandora_object_alter($fedora_object) {}
* *
* @param type $islandora_object * @param type $islandora_object
* A Tuque FedoraObject * A Tuque FedoraObject
* @param array $content_models
* @param string $collection_pid
*/ */
function hook_islandora_ingest_pre_ingest($islandora_object, $content_models, $collection_pid) {} function hook_islandora_ingest_pre_ingest($islandora_object) {}
/** /**
* Allow modification of objects of a certain content model before ingesting. * Allow modification of objects of a certain content model before ingesting.
* *
* @see hook_islandora_ingest_pre_ingest() * @see hook_islandora_ingest_pre_ingest()
*/ */
function hook_CMODEL_PID_islandora_ingest_pre_ingest($islandora_object, $content_models, $collection_pid) {} function hook_CMODEL_PID_islandora_ingest_pre_ingest($islandora_object) {}
/** /**
* Allow modules to setup for the purge of a datastream. * Allow modules to setup for the purge of a datastream.
@ -218,3 +216,9 @@ function hook_islandora_required_objects() {}
* @see islandora_get_viewer_callback() * @see islandora_get_viewer_callback()
*/ */
function hook_islandora_viewer_info() {} function hook_islandora_viewer_info() {}
/**
* Returns a list of datastreams that are determined to be undeletable.
*/
function hook_islandora_undeletable_datastreams(array $models) {}

4
islandora.info

@ -1,9 +1,13 @@
name = Islandora name = Islandora
description = "View and manage Fedora objects" description = "View and manage Fedora objects"
package = Islandora package = Islandora
dependencies[] = tuque
version = 7.x-dev version = 7.x-dev
core = 7.x core = 7.x
configure = admin/islandora/configure configure = admin/islandora/configure
stylesheets[all][] = css/islandora.base.css stylesheets[all][] = css/islandora.base.css
stylesheets[all][] = css/islandora.theme.css stylesheets[all][] = css/islandora.theme.css
files[] = includes/MimeDetect.inc
files[] = includes/DublinCore.inc
files[] = includes/IslandoraTuque.inc
php = 5.3 php = 5.3

5
islandora.install

@ -2,7 +2,8 @@
/** /**
* @file * @file
* This file contains all install functions. *
* This file contains all install related hooks.
*/ */
/** /**
@ -12,7 +13,6 @@
*/ */
function islandora_install() { function islandora_install() {
module_load_include('inc', 'islandora', 'includes/solution_packs'); module_load_include('inc', 'islandora', 'includes/solution_packs');
// install object(s)
islandora_install_solution_pack('islandora'); islandora_install_solution_pack('islandora');
} }
@ -23,6 +23,5 @@ function islandora_install() {
*/ */
function islandora_uninstall() { function islandora_uninstall() {
module_load_include('inc', 'islandora', 'includes/solution_packs'); module_load_include('inc', 'islandora', 'includes/solution_packs');
// uninstall callback
islandora_install_solution_pack('islandora', 'uninstall'); islandora_install_solution_pack('islandora', 'uninstall');
} }

455
islandora.module

@ -1,6 +1,6 @@
<?php <?php
/* /**
* @file * @file
* *
* islandora.module: defines paths (drupal menu items) as entry points and acts as a hub for dispatching tasks to other modules. * islandora.module: defines paths (drupal menu items) as entry points and acts as a hub for dispatching tasks to other modules.
@ -20,7 +20,10 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with the program. If not, see <http ://www.gnu.org/licenses/>. * along with the program. If not, see <http ://www.gnu.org/licenses/>.
*/ */
module_load_include('inc', 'islandora', 'includes/globals');
// Common datastreams
define('DS_COMP_STREAM', 'DS-COMPOSITE-MODEL');
// Permissions // Permissions
define('FEDORA_VIEW', 'view fedora repository'); define('FEDORA_VIEW', 'view fedora repository');
@ -34,16 +37,21 @@ define('FEDORA_MANAGE', 'manage fedora items');
// Hooks // Hooks
define('ISLANDORA_VIEW_HOOK', 'islandora_view_object'); define('ISLANDORA_VIEW_HOOK', 'islandora_view_object');
define('ISLANDORA_EDIT_HOOK', 'islandora_edit_object'); define('ISLANDORA_EDIT_HOOK', 'islandora_edit_object');
define('ISLANDORA_PRE_INGEST_HOOK', 'islandora_ingest_pre_ingest');
define('ISLANDORA_POST_INGEST_HOOK', 'islandora_ingest_post_ingest'); define('ISLANDORA_POST_INGEST_HOOK', 'islandora_ingest_post_ingest');
define('ISLANDORA_PRE_PURGE_OBJECT_HOOK', 'islandora_pre_purge_object'); define('ISLANDORA_PRE_PURGE_OBJECT_HOOK', 'islandora_pre_purge_object');
define('ISLANDORA_POST_PURGE_OBJECT_HOOK', 'islandora_post_purge_object');
define('ISLANDORA_INGEST_STEP_HOOK', 'islandora_ingest_steps');
define('ISLANDORA_PRE_PURGE_DATASTREAM_HOOK', 'islandora_pre_purge_datastream');
define('ISLANDORA_POST_PURGE_DATASTREAM_HOOK', 'islandora_post_purge_datastream');
/** /**
* Implements hook_menu(). * Implements hook_menu().
* we need some standard entry points so we can have consistent urls for different Object actions *
* We need some standard entry points so we can have consistent urls for different Object actions
*/ */
function islandora_menu() { function islandora_menu() {
$items = array(); $items = array();
$items['admin/islandora'] = array( $items['admin/islandora'] = array(
'title' => 'Islandora', 'title' => 'Islandora',
'description' => "Configure settings associated with Islandora.", 'description' => "Configure settings associated with Islandora.",
@ -60,7 +68,6 @@ function islandora_menu() {
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
'weight' => -1, 'weight' => -1,
); );
$items['admin/islandora/solution_packs'] = array( $items['admin/islandora/solution_packs'] = array(
'title' => 'Solution packs', 'title' => 'Solution packs',
'description' => 'Install content models and collections required by installed solution packs.', 'description' => 'Install content models and collections required by installed solution packs.',
@ -68,147 +75,131 @@ function islandora_menu() {
'access arguments' => array(FEDORA_ADD_DS), 'access arguments' => array(FEDORA_ADD_DS),
'file' => 'includes/solution_packs.inc', 'file' => 'includes/solution_packs.inc',
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
); );
$items['islandora/object/%islandora_object/manage/ingest'] = array(
'title' => 'Add an object',
'page callback' => 'islandora_ingest_callback',
'page arguments' => array(2),
'file' => 'includes/ingest-menu.inc',
'type' => MENU_LOCAL_ACTION,
'access callback' => 'islandora_ingest_access_callback',
'access arguments' => array(2, FEDORA_INGEST),
);
$items['islandora'] = array( $items['islandora'] = array(
'title' => 'Islandora Repository', 'title' => 'Islandora Repository',
'page callback' => 'islandora_view_default_object', 'page callback' => 'islandora_view_default_object',
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
'access arguments' => array(FEDORA_VIEW), 'access arguments' => array(FEDORA_VIEW),
); );
$items['islandora/object/%islandora_object'] = array( $items['islandora/object/%islandora_object'] = array(
'title' => 'Repository', 'title' => 'Repository',
'page callback' => 'islandora_view_object', 'page callback' => 'islandora_view_object',
'page arguments' => array(2), 'page arguments' => array(2),
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_access_callback',
'access arguments' => array(2, FEDORA_VIEW), 'access arguments' => array(FEDORA_VIEW, 2),
); );
$items['islandora/object/%islandora_object/view'] = array( $items['islandora/object/%islandora_object/view'] = array(
'title' => 'View', 'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK, 'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -1, 'weight' => -1,
); );
$items['islandora/object/%islandora_object/view/default'] = array( $items['islandora/object/%islandora_object/view/default'] = array(
'title' => 'View', 'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK, 'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -1, 'weight' => -1,
); );
$items['islandora/object/%islandora_object/manage'] = array( $items['islandora/object/%islandora_object/manage'] = array(
'title' => 'Manage', 'title' => 'Manage',
'page callback' => 'islandora_edit_object', 'page callback' => 'islandora_edit_object',
'page arguments' => array(2), 'page arguments' => array(2),
'type' => MENU_LOCAL_TASK, 'type' => MENU_LOCAL_TASK,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_access_callback',
'access arguments' => array(2, FEDORA_MODIFY_STATE), 'access arguments' => array(FEDORA_MODIFY_STATE, 2),
); );
$items['islandora/object/%islandora_object/manage/datastreams'] = array( $items['islandora/object/%islandora_object/manage/datastreams'] = array(
'title' => 'Datastreams', 'title' => 'Datastreams',
'type' => MENU_DEFAULT_LOCAL_TASK, 'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10, 'weight' => -10,
); );
$items['islandora/object/%islandora_object/manage/properties'] = array( $items['islandora/object/%islandora_object/manage/properties'] = array(
'title' => 'Properties', 'title' => 'Properties',
'page callback' => 'drupal_get_form', 'page callback' => 'drupal_get_form',
'file' => 'includes/object_properties.inc', 'file' => 'includes/object_properties.form.inc',
'page arguments' => array('islandora_edit_properties_form', 2), 'page arguments' => array('islandora_object_properties_form', 2),
'type' => MENU_LOCAL_TASK, 'type' => MENU_LOCAL_TASK,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_access_callback',
'access arguments' => array(2, FEDORA_MODIFY_STATE), 'access arguments' => array(FEDORA_MODIFY_STATE, 2),
'weight' => -5, 'weight' => -5,
); );
$items['islandora/object/%islandora_object/delete'] = array( $items['islandora/object/%islandora_object/delete'] = array(
'title' => 'Delete object', 'title' => 'Delete object',
'file' => 'includes/purge.form.inc', 'file' => 'includes/delete_object.form.inc',
'page callback' => 'drupal_get_form', 'page callback' => 'drupal_get_form',
'page arguments' => array('islandora_purge_object', 2), 'page arguments' => array('islandora_delete_object_form', 2),
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_access_callback',
'access arguments' => array(2, FEDORA_PURGE), 'access arguments' => array(FEDORA_PURGE, 2),
); );
$items['islandora/object/%islandora_object/manage/datastreams/add'] = array( $items['islandora/object/%islandora_object/manage/datastreams/add'] = array(
'title' => 'Add a datastream', 'title' => 'Add a datastream',
'file' => 'includes/datastream.inc', 'file' => 'includes/add_datastream.form.inc',
'page callback' => 'drupal_get_form', 'page callback' => 'drupal_get_form',
'page arguments' => array('islandora_add_datastream_form', 2), 'page arguments' => array('islandora_add_datastream_form', 2),
'type' => MENU_LOCAL_ACTION, 'type' => MENU_LOCAL_ACTION,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_access_callback',
'access arguments' => array(2, FEDORA_ADD_DS) 'access arguments' => array(FEDORA_ADD_DS, 2)
); );
$items['islandora/object/%islandora_object/manage/datastreams/add/autocomplete'] = array( $items['islandora/object/%islandora_object/manage/datastreams/add/autocomplete'] = array(
'file' => 'includes/datastream.inc', 'file' => 'includes/add_datastream.form.inc',
'page callback' => 'islandora_datastream_autocomplete_callback', 'page callback' => 'islandora_add_datastream_form_autocomplete_callback',
'page arguments' => array(2), 'page arguments' => array(2),
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_access_callback',
'access arguments' => array(2, FEDORA_ADD_DS) 'access arguments' => array(FEDORA_ADD_DS, 2)
); );
$items['islandora/object/%islandora_object/datastream/%islandora_datastream'] = array(
$items['islandora/object/%islandora_object/datastream/%'] = array(
'title' => 'View datastream', 'title' => 'View datastream',
'page callback' => 'islandora_view_datastream', 'page callback' => 'islandora_view_datastream',
'page arguments' => array(2, 4), 'page arguments' => array(4),
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc', 'file' => 'includes/datastream.inc',
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(2, FEDORA_VIEW), 'access arguments' => array(FEDORA_VIEW, 2, 4),
'load arguments' => array('%map'),
); );
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/view'] = array(
$items['islandora/object/%islandora_object/datastream/%/view'] = array(
'title' => 'View datastream', 'title' => 'View datastream',
'type' => MENU_DEFAULT_LOCAL_TASK, 'type' => MENU_DEFAULT_LOCAL_TASK,
); );
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/download'] = array(
$items['islandora/object/%islandora_object/datastream/%/download'] = array(
'title' => 'Download datastream', 'title' => 'Download datastream',
'page callback' => 'islandora_view_datastream', 'page callback' => 'islandora_download_datastream',
'page arguments' => array(2, 4, 5), 'page arguments' => array(4),
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc', 'file' => 'includes/datastream.inc',
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(2, FEDORA_VIEW), 'access arguments' => array(FEDORA_VIEW, 2, 4),
'load arguments' => array('%map'),
); );
$items['islandora/object/%islandora_object/datastream/%islandora_datastreams/edit'] = array(
$items['islandora/object/%islandora_object/datastream/%/edit'] = array(
'title' => 'Edit datastream', 'title' => 'Edit datastream',
'page callback' => 'islandora_edit_datastream', 'page callback' => 'islandora_edit_datastream',
'page arguments' => array(2, 4), 'page arguments' => array(2, 4),
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc', 'file' => 'includes/datastream.inc',
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(2, FEDORA_METADATA_EDIT), 'access arguments' => array(FEDORA_METADATA_EDIT, 2, 4),
'load arguments' => array('%map'),
); );
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/delete'] = array(
$items['islandora/object/%islandora_object/datastream/%/delete'] = array( 'title' => 'Delete data stream',
'title' => 'Purge data stream',
'page callback' => 'drupal_get_form', 'page callback' => 'drupal_get_form',
'page arguments' => array('islandora_purge_datastream', 2, 4), 'page arguments' => array('islandora_delete_datastream_form', 4),
'file' => 'includes/purge.form.inc', 'file' => 'includes/delete_datastream.form.inc',
'type' => MENU_CALLBACK, 'type' => MENU_CALLBACK,
'access callback' => 'islandora_access_callback', 'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(2, FEDORA_PURGE), 'access arguments' => array(FEDORA_PURGE, 2, 4),
'load arguments' => array('%map'),
);
$items['islandora/ingest'] = array(
'title' => 'Add an Object',
'page callback' => 'islandora_ingest_callback',
'file' => 'includes/ingest.menu.inc',
'type' => MENU_SUGGESTED_ITEM,
'access arguments' => array(FEDORA_INGEST),
); );
return $items; return $items;
} }
@ -225,8 +216,6 @@ function islandora_admin_paths() {
/** /**
* Implements hook_theme(). * Implements hook_theme().
*
* @return array
*/ */
function islandora_theme() { function islandora_theme() {
return array( return array(
@ -252,8 +241,6 @@ function islandora_theme() {
/** /**
* Implements hook_permission(). * Implements hook_permission().
*
* @return array
*/ */
function islandora_permission() { function islandora_permission() {
return array( return array(
@ -302,105 +289,94 @@ function islandora_forms($form_id) {
} }
/** /**
* determines whether we can see the object or not * Checks whether the user can access the given object with the given permission.
* checks PID namespace permissions, and user permissions *
* @global object $user * Checks for object existance, accessiblitly, namespace permissions, and user permissions
* @param string $op
* @param string $pid
* *
* @return boolean * @see islandora_object_load() To find potential solutions to enable page not found errors.
*
* @param string $perm
* The user permission to test for.
* @param FedoraObject $object
* The object to test, if NULL given the object doesn't exist or is inaccessible.
*
* @return boolean
* TRUE if the user is allowed to access this object, FALSE otherwise.
*/ */
function islandora_access_callback($object = NULL, $perm = NULL) { function islandora_object_access_callback($perm, $object = NULL) {
if (!$object || !$perm) { module_load_include('inc', 'islandora', 'includes/utilities');
return FALSE; return user_access($perm) && is_object($object) && islanodra_namespace_accessible($object->id);
} }
$is_restricted = variable_get('islandora_namespace_restriction_enforced', FALSE);
if (!$is_restricted) {
$namespace_access = TRUE;
}
else {
$pid_namespace = substr($object->id, 0, strpos($object->id, ':') + 1); // Get the namespace (with colon)
$allowed_namespaces = explode(" ", variable_get('islandora_pids_allowed', 'default: demo: changeme: islandora: ilives: islandora-book: books: newspapers: '));
$namespace_access = in_array($pid_namespace, $allowed_namespaces);
}
return ($namespace_access && user_access($perm)); /**
* Checks whether the user can access the given object and datastream with the given permission.
*
* Checks for object existance, accessiblitly, namespace permissions, and user permissions
*
* @see islandora_object_load() To find potential solutions to enable page not found errors.
*
* @param string $perm
* The user permission to test for.
* @param FedoraObject $object
* The object to test, if NULL given the object doesn't exist or is inaccessible.
* @param FedoraDatastream $datastream
* The datastream to test, if NULL given the datastream doesn't exist or is inaccessible.
*
* @return boolean
* TRUE if the user is allowed to access this object, FALSE otherwise.
*/
function islandora_object_datastream_access_callback($perm, $object = NULL, $datastream = NULL) {
module_load_include('inc', 'islandora', 'includes/utilities');
return user_access($perm) && is_object($object) && islanodra_namespace_accessible($object->id) && is_object($datastream);
} }
/** /**
* a function to call other modules edit page. If there are not any modules * Renders the given objects manage page. Its possible to modify the output of this function if 'ISLANDORA_EDIT_HOOK' is
* that handle this function this module will build a default page. * implemented in other modules.
* @global object $user *
* @param string $object_id * If no modules implement 'ISLANDORA_EDIT_HOOK' then this function returns the default manage view.
*
* @param FedoraObject $object
* The object to manage.
*
* @return string * @return string
* The HTML repersentation of the manage object page.
*/ */
function islandora_edit_object($object) { function islandora_edit_object(FedoraObject $object) {
if (!$object) {
return drupal_not_found();
}
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
// Accumulate the output.
$output = array(); $output = array();
// Call cmodel oriented variants first.
foreach (islandora_build_hook_list(ISLANDORA_EDIT_HOOK, $object->models) as $hook) { foreach (islandora_build_hook_list(ISLANDORA_EDIT_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object); $temp = module_invoke_all($hook, $object);
if (!empty($temp)) { if (!empty($temp)) {
$output = array_merge_recursive($output, $temp); $output = array_merge_recursive($output, $temp);
} }
} }
// Add in the default, if we did not get any results.
if (empty($output)) { if (empty($output)) {
$output = islandora_default_islandora_edit_object($object); $output = islandora_default_islandora_edit_object($object); // Add in the default, if we did not get any results.
} }
arsort($output); arsort($output);
drupal_alter(ISLANDORA_EDIT_HOOK, $object, $output); drupal_alter(ISLANDORA_EDIT_HOOK, $object, $output);
return implode('', $output); return implode('', $output);
} }
/** /**
* edit properties form * Renders the default manage object page for the given object.
* @param type $object_id
* @return string
*/
function islandora_edit_properties($object_id) {
$object = islandora_object_load($object_id);
if (isset($object)) {
module_load_include('inc', 'islandora', 'includes/object_properties');
$form = drupal_get_form('islandora_edit_properties_form', $object);
drupal_set_title($object->label);
return drupal_render($form);
}
return "";
}
/**
* Builds a default page for the edit tab.
* *
* @param object $fedora_object * @param FedoraObject $object
* A tuque Fedora Object * The object used to render the manage object page.
*
* @return array
* The default rendering of the object manage page, indexed at 'Default Edit output'.
*/ */
function islandora_default_islandora_edit_object($fedora_object) { function islandora_default_islandora_edit_object(FedoraObject $object) {
$output = theme('islandora_default_edit', array( $output = theme('islandora_default_edit', array('islandora_object' => $object));
'islandora_object' => $fedora_object,
));
return array('Default Edit output' => $output); return array('Default Edit output' => $output);
} }
/** /**
* Page callback for the path "islandora". * Page callback for the path "islandora".
* *
* Redirects to the view of the object indicated by the Drupal variable * Redirects to the view of the object indicated by the Drupal variable 'islandora_repository_pid'.
* islandora_repository_pid.
*/ */
function islandora_view_default_object() { function islandora_view_default_object() {
$pid = variable_get('islandora_repository_pid', 'islandora:root'); $pid = variable_get('islandora_repository_pid', 'islandora:root');
@ -408,59 +384,49 @@ function islandora_view_default_object() {
} }
/** /**
* The view entry point. modules should implement hook_islandora_view_object for the Fedora Content models that * Renders the default view object page for the given object.
*
* Modules should implement ISLANDORA_VIEW_HOOK for the Fedora Content models that
* their modules want to provide a view for. * their modules want to provide a view for.
* @global object $user *
* @param string $object_id * If no modules implement the hook then the default view object page will be rendered.
*
* @param FedoraObject $object
* The object to view.
* *
* @return string * @return string
* The html repersentation of this object.
*/ */
function islandora_view_object($fedora_object = NULL) { function islandora_view_object(FedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/breadcrumb'); module_load_include('inc', 'islandora', 'includes/breadcrumb');
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
drupal_set_breadcrumb(islandora_get_breadcrumbs($object));
global $user; // Optional pager parameters
if (!$fedora_object) {
return drupal_not_found();
}
// set breadcrumbs
drupal_set_breadcrumb(islandora_get_breadcrumbs($fedora_object));
// optional pager parameters
$page_number = (empty($_GET['page'])) ? '1' : $_GET['page']; $page_number = (empty($_GET['page'])) ? '1' : $_GET['page'];
$page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize']; $page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize'];
// Accumulate the output.
$output = array(); $output = array();
foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $object->models) as $hook) {
// Call cmodel oriented variants first. $temp = module_invoke_all($hook, $object, $page_number, $page_size); // @todo Remove page number and size from this hook, implementers of the hook should use drupal page handling directly.
foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $fedora_object->models) as $hook) {
$temp = module_invoke_all($hook, $fedora_object, $page_number, $page_size);
if (!empty($temp)) { if (!empty($temp)) {
$output = array_merge_recursive($output, $temp); $output = array_merge_recursive($output, $temp);
} }
} }
// Add in the default, if we did not get any results.
if (empty($output)) { if (empty($output)) {
$output = islandora_default_islandora_view_object($fedora_object); $output = islandora_default_islandora_view_object($object); // No results, use the default view.
} }
arsort($output); arsort($output);
drupal_alter(ISLANDORA_VIEW_HOOK, $object, $output);
drupal_alter(ISLANDORA_VIEW_HOOK, $fedora_object, $output);
return implode('', $output); return implode('', $output);
} }
/** /**
* If there are no modules registered to handle this objects cmodels or there are * Renders the default view object page for the given object.
* not any cmodels specified this will create a default display.
* *
* @param FedoraObject $object * @param FedoraObject $object
* The object whose display we are to render. * The object used to render the view object page.
*
* @return array * @return array
* The default rendering of the object view page, indexed at 'Default output'.
*/ */
function islandora_default_islandora_view_object($object) { function islandora_default_islandora_view_object($object) {
$output = theme('islandora_default', array('islandora_object' => $object)); $output = theme('islandora_default', array('islandora_object' => $object));
@ -468,106 +434,73 @@ function islandora_default_islandora_view_object($object) {
} }
/** /**
* A helper function to get a connection and return an object * A helper function to get a connection and return an object for objects specified in the menu path as '%islandora_object'.
*
* This should only be used by the Drupal menu wildcard system! As for non existing objects this will return page not found.
*
* After some research drupal_not_found(), drupal_access_denied() and others can not be safetly used at this level. Nor can
* They be used at the "access callback" level. Not without hacking core, also it seems roling our own versions of these
* functions will be fruitless. We can still use drupal_goto() though, if we redirect to our own pages for 404, 500 etc. we
* Will be able to deliever the correct message to users.
*
* @todo For non accessible objects to the user this should return access denied.
* @todo When the repository down this should return a 500 error or a site offline notice.
* *
* @global object $user
* @param string $object_id * @param string $object_id
* The pid of an object in the menu path identified by '%islandora_object'.
*
* @return FedoraObject * @return FedoraObject
* If the given object id exists in the repository then this returns a FedoraObject, if no object was found it returns FALSE which triggers a drupal_page_not_found(), if the
* object was inaccessible then NULL is returned, and the access callback will catch that case, triggering an access denied.
*/ */
function islandora_object_load($object_id) { function islandora_object_load($object_id) {
module_load_include('inc', 'islandora', 'includes/tuque'); static $object = NULL, $load_failed = FALSE; // Assume inaccessible.
$islandora_tuque = &drupal_static(__FUNCTION__); if ($load_failed || isset($object)) {
return $object;
if (!$islandora_tuque) {
$islandora_tuque = new IslandoraTuque();
} }
$object = islandora_get_object_by_id($object_id); // Either NULL or FALSE.
if (IslandoraTuque::exists()) { if (!isset($object)) {
try { $load_failed = TRUE;
$fedora_object = $islandora_tuque->repository->getObject($object_id);
} catch (Exception $e) {
return NULL;
}
drupal_alter('islandora_object', $fedora_object);
return $fedora_object;
}
else {
IslandoraTuque::getError();
return NULL;
} }
return $object;
} }
/** /**
* A helper function to get a connection and purge an object * A helper function to get an datastream specified as '%islandora_datastream' for the object specified in the menu path as '%islandora_object'.
* *
* @global object $user * This should only be used by the Drupal menu wildcard system! As for non existing datastreams this will return page not found.
* @param string $object_id *
* @return FedoraObject * The following settings are required for any menu paths which intent to use this auto loader.
*
* @code
* 'load arguments' => array('%map'),
* @endcode
*
* @see islandora_object_load() for solutions to access/not found problems.
*
* @todo For non accessible datastreams to the user this should return access denied.
* @todo Is there anything we can do to enhance caching?
*
* @param string $datastream_id
* The dsid of the datastream specified as '%islandora_datastream' to fetch from the given object in the menu path identified by '%islandora_object'.
*
* @return FedoraDatastream
* If the given datastream id exists in the object then this returns a FedoraDatastream, in other cases this aborts.
*/ */
function islandora_object_purge($object_id) { function islandora_datastream_load($datastream_id, $map) {
if (!$object_id) { static $datastream = NULL, $load_failed = FALSE; // @hack for bug in drupal_not_found() when used before the menu callback. Infinite recursion bug.
drupal_set_message(t('Cannot remove object, object id not set')); if ($load_failed || isset($datastream)) {
return; return $datastream;
}
// load object
$object = islandora_object_load($object_id);
if (!$object) {
drupal_set_message(t('Could not remove object, object not found'));
return;
}
module_load_include('inc', 'islandora', 'includes/utilities');
$content_models = $object->models;
$arr = array();
foreach (islandora_build_hook_list(ISLANDORA_PRE_PURGE_OBJECT_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object);
if (!empty($temp)) {
$arr = array_merge_recursive($arr, $temp);
}
}
if (isset($arr['delete']) && $arr['delete']) {
try {
$object->delete();
} catch (Exception $e) {
drupal_set_message(t('Error deleting Islandora object %s %e', array('%s' => $object_id, '%e' => $e)), 'error');
return "";
}
} }
else { foreach ($map as $element) {
try { $is_fedora_object = is_object($element) && strtolower(get_class($element)) == 'fedoraobject'; // @todo Probably a better way to check types by now.
$object->repository->purgeObject($object_id); if ($is_fedora_object && isset($element[$datastream_id])) { // @todo check for access denied to this datastream so we can show the access denied page instead.
} catch (Exception $e) { $datastream = $element[$datastream_id];
drupal_set_message(t('Error purging Islandora object %s %e', array('%s' => $object_id, '%e' => $e)), 'error'); return $datastream;
return "";
} }
} }
$load_failed = TRUE;
module_invoke_all('islandora_post_purge_object', $object_id, $content_models); // notify modules post deletion return $datastream; // @todo Test
}
/**
* Ingest access callback
*/
function islandora_ingest_access_callback($object, $perm) {
if (islandora_access_callback($object, $perm) === FALSE) {
return FALSE;
}
$ingest_registry = module_invoke_all('islandora_ingest_registry', $object);
if (count($ingest_registry) > 0) {
return TRUE;
}
else {
return FALSE;
}
} }
/** /**
@ -634,7 +567,9 @@ function islandora_islandora_required_objects() {
); );
} }
/**
* Implements islandora_undeleteable_datastreams().
*/
function islandora_islandora_undeletable_datastreams(array $models) {
return array('DC');
}

2
theme/islandora-object-edit.tpl.php

@ -11,7 +11,7 @@
* to get the contents of a datastream * to get the contents of a datastream
* $object['dsid']->content * $object['dsid']->content
* *
* $dublin_core is a Dublin_Core object * $dublin_core is a DublinCore object
* which is an array of elements, such as dc.title * which is an array of elements, such as dc.title
* and each element has an array of values. dc.title can have none, one or many titles * and each element has an array of values. dc.title can have none, one or many titles
* this is the case for all dc elements. * this is the case for all dc elements.

10
theme/islandora-object.tpl.php

@ -17,7 +17,7 @@
* to test if a datastream exists isset($object['dsid']) * to test if a datastream exists isset($object['dsid'])
* *
* to iterate over datastreams: * to iterate over datastreams:
* foreach($object as $ds) { * foreach ($object as $ds) {
* $ds->label, etc * $ds->label, etc
* } * }
* *
@ -39,7 +39,7 @@
* $ds->content - The content of the datastream * $ds->content - The content of the datastream
* $ds->url - The URL. This is only valid for R and E datastreams. * $ds->url - The URL. This is only valid for R and E datastreams.
* *
* $dublin_core is a Dublin_Core object * $dublin_core is a DublinCore object
* which is an array of elements, such as dc.title * which is an array of elements, such as dc.title
* and each element has an array of values. dc.title can have none, one or many titles * and each element has an array of values. dc.title can have none, one or many titles
* this is the case for all dc elements. * this is the case for all dc elements.
@ -47,7 +47,7 @@
* *
* *
* we can get a list of datastreams by doing * we can get a list of datastreams by doing
* foreach ($object as $ds){ * foreach ($object as $ds) {
* do something here * do something here
* } * }
* *
@ -80,8 +80,8 @@
<?php if ($parent_collections): ?> <?php if ($parent_collections): ?>
<dt>Collections</dt> <dt>Collections</dt>
<dd> <dd>
<?php foreach ($parent_collections as $key => $value): ?> <?php foreach ($parent_collections as $collection): ?>
<div><?php print $value['label_link'] ?></div> <div><?php print l($collection->label, "islandora/object/{$collection->id}"); ?></div>
<?php endforeach; ?> <?php endforeach; ?>
</dd> </dd>
<?php endif; ?> <?php endif; ?>

5
theme/islandora.theme.inc

@ -59,11 +59,10 @@ function islandora_preprocess_islandora_default(&$variables) {
drupal_add_js('misc/form.js'); drupal_add_js('misc/form.js');
drupal_add_js('misc/collapse.js'); drupal_add_js('misc/collapse.js');
$islandora_object = $variables['islandora_object']; $islandora_object = $variables['islandora_object'];
module_load_include('inc', 'islandora', 'includes/islandora_dublin_core');
module_load_include('inc', 'islandora', 'includes/utilities'); module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('inc', 'islandora', 'includes/datastream'); module_load_include('inc', 'islandora', 'includes/datastream');
$variables['parent_collections'] = islandora_datastream_get_parents($islandora_object); $variables['parent_collections'] = islandora_get_parents_from_rels_ext($islandora_object);
$datastreams = array(); $datastreams = array();
foreach ($islandora_object as $ds) { foreach ($islandora_object as $ds) {
@ -89,7 +88,7 @@ function islandora_preprocess_islandora_default(&$variables) {
try { try {
$dc = $islandora_object['DC']->content; $dc = $islandora_object['DC']->content;
//$dc_xml = simplexml_load_string($dc); //$dc_xml = simplexml_load_string($dc);
$dc_object = Dublin_Core::import_from_xml_string($dc); $dc_object = DublinCore::import_from_xml_string($dc);
$dc_array = $dc_object->as_formatted_array(); $dc_array = $dc_object->as_formatted_array();
} catch (Exception $e) { } catch (Exception $e) {
drupal_set_message(t('Error retrieving object %s %t', array('%s' => $islandora_object->id, '%t' => $e->getMessage())), 'error', FALSE); drupal_set_message(t('Error retrieving object %s %t', array('%s' => $islandora_object->id, '%t' => $e->getMessage())), 'error', FALSE);

Loading…
Cancel
Save