Browse Source

Merge pull request #203 from nigelgbanks/7.x-ingest

7.x ingest
pull/209/merge
Jonathan Green 12 years ago
parent
commit
dd7a09edc9
  1. 54
      README
  2. 10
      admin/islandora.admin.inc
  3. 18
      includes/DublinCore.inc
  4. 33
      includes/IslandoraTuque.inc
  5. 55
      includes/IslandoraTuqueWrapper.inc
  6. 0
      includes/MimeDetect.inc
  7. 231
      includes/add_datastream.form.inc
  8. 48
      includes/breadcrumb.inc
  9. 527
      includes/datastream.inc
  10. 66
      includes/delete_datastream.form.inc
  11. 50
      includes/delete_object.form.inc
  12. 47
      includes/ingest-menu.inc
  13. 428
      includes/ingest.form.inc
  14. 66
      includes/ingest.menu.inc
  15. 237
      includes/islandora.ingest.inc
  16. 120
      includes/object_properties.form.inc
  17. 125
      includes/object_properties.inc
  18. 138
      includes/purge.form.inc
  19. 181
      includes/solution_packs.inc
  20. 307
      includes/utilities.inc
  21. 46
      islandora.api.php
  22. 3
      islandora.info
  23. 5
      islandora.install
  24. 645
      islandora.module
  25. 10
      theme/islandora-object-edit.tpl.php
  26. 21
      theme/islandora-object.tpl.php
  27. 13
      theme/islandora.theme.inc

54
README

@ -1,9 +1,59 @@
CONTENTS OF THIS FILE
---------------------
* summary
* requirements
* installation
* configuration
* customization
* troubleshooting
* faq
* contact
* sponsors
SUMMARY
-------
Islandora Fedora Repository Module
For installation and customization instructions please see the documentation and the DuraSpace Wiki:
For installation and customization instructions please see the documentation
and the DuraSpace Wiki:
https://wiki.duraspace.org/display/ISLANDORA/Islandora
All bugs, feature requests and improvement suggestions are tracked at the DuraSpace JIRA:
All bugs, feature requests and improvement suggestions are tracked at the
DuraSpace JIRA:
https://jira.duraspace.org/browse/ISLANDORA
REQUIREMENTS
------------
INSTALLATION
------------
CONFIGURATION
-------------
CUSTOMIZATION
-------------
TROUBLESHOOTING
---------------
F.A.Q.
------
CONTACT
-------
SPONSORS
--------

10
admin/islandora.admin.inc

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

18
includes/islandora_dublin_core.inc → includes/DublinCore.inc

@ -2,6 +2,7 @@
/**
* @file
*
* Implements a simple class for working with Dublin Core data and exporting it
* back to XML. Inspiration and design shamelessly stolen from the pyfedora
* project at http://pypi.python.org/pypi/pyfedora/0.1.0
@ -10,7 +11,7 @@
/**
* Dublin Core Class
*/
class Dublin_Core {
class DublinCore {
public $dc = array(
'dc:title' => array(),
@ -32,11 +33,12 @@ class Dublin_Core {
public $owner;
/**
* Constructs a Dublin_Core object from a Fedora_Item object and populates
* the $dc array.
* @param <type> $item
* Constructs a DublinCore object from a Fedora_Item object and populates the
* $dc array.
*
* @param string $dc_xml
*/
function Dublin_Core($dc_xml = NULL) {
function DublinCore($dc_xml = NULL) {
if (!empty($dc_string)) {
$this->dc = self::import_from_xml_string($dc_xml);
}
@ -134,14 +136,15 @@ class Dublin_Core {
/**
* Creates a new instance of the class by parsing dc_xml
*
* @param string $dc_xml
* @return Dublin_Core
* @return DublinCore
*/
static function import_from_xml_string($dc_xml) {
$dc_doc = new DomDocument();
if ($dc_doc->loadXML($dc_xml)) {
$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) {
array_push($new_dc->dc[$child->nodeName], $child->nodeValue);
}
@ -153,4 +156,3 @@ class Dublin_Core {
}
}

33
includes/tuque.inc → includes/IslandoraTuque.inc

@ -2,6 +2,7 @@
/**
* @file
*
* This file contains a class to include the Tuque php library.
*/
@ -77,11 +78,11 @@ class IslandoraTuque {
}
if (self::exists()) {
$this->connection = new RepositoryConnection($url, $user_string, $pass_string);
$this->connection = new IslandoraRepositoryConnection($url, $user_string, $pass_string);
$this->connection->reuseConnection = TRUE;
$this->api = new FedoraApi($this->connection);
$this->cache = new SimpleCache();
$this->repository = new FedoraRepository($this->api, $this->cache);
$this->api = new IslandoraFedoraApi($this->connection);
$this->cache = new IslandoraSimpleCache();
$this->repository = new IslandoraFedoraRepository($this->api, $this->cache);
}
}
@ -97,3 +98,27 @@ class IslandoraTuque {
}
}
/**
* 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) {
if (IslandoraTuque::exists()) {
require_once(__DIR__ . '/IslandoraTuqueWrapper.inc');
try {
$tuque = new IslandoraTuque();
} catch (Exception $e) {
drupal_set_message(t('Unable to connect to the repository %e', array('%e' => $e)), 'error');
}
}
else {
return NULL;
}
}
return $tuque;
}

55
includes/IslandoraTuqueWrapper.inc

@ -0,0 +1,55 @@
<?php
/**
* @file
*
* Wrapper around the tuque library, allows for autoloading of Islandora Tuque
* Objects.
*
* @todo Overload functions and apply pre/post hooks.
*/
class IslandoraFedoraRepository extends FedoraRepository {
protected $queryClass = 'IslandoraRepositoryQuery';
protected $newObjectClass = 'IslandoraNewFedoraObject';
protected $objectClass = 'IslandoraFedoraObject';
}
class IslandoraRepositoryQuery extends RepositoryQuery {}
class IslandoraNewFedoraObject extends NewFedoraObject {
protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream';
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
}
class IslandoraFedoraObject extends FedoraObject {
protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream';
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
}
class IslandoraRepositoryConnection extends RepositoryConnection {}
class IslandoraFedoraApi extends FedoraApi {}
class IslandoraSimpleCache extends SimpleCache {}
class IslandoraNewFedoraDatastream extends NewFedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraDatastream extends FedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraRelsExt extends FedoraRelsExt {}
class IslandoraFedoraRelsInt extends FedoraRelsInt {}

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

231
includes/add_datastream.form.inc

@ -0,0 +1,231 @@
<?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');
module_load_include('inc', 'islandora', 'includes/utilities');
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),
// Assume its specified in MB
'file_validate_size' => array($upload_size * 1024 * 1024),
),
),
'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
* 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_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
* vThe 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');
module_load_include('inc', 'islandora', 'includes/utilities');
$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);
}

48
includes/breadcrumb.inc

@ -2,23 +2,36 @@
/**
* @file
*
* 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) {
$breadcrumbs = array();
islandora_get_breadcrumbs_recursive($object->id, $breadcrumbs, $object->repository);
if (isset($breadcrumbs[0])) {
// Remove the actual object.
unset($breadcrumbs[0]);
}
$breadcrumbs = array_reverse($breadcrumbs);
return $breadcrumbs;
}
@ -27,14 +40,19 @@ function islandora_get_breadcrumbs($object) {
*
* @todo Make fully recursive...
*
* @global type $base_url
* @param type $pid
* @param type $breadcrumbs
* @param type $level
* @todo Could use some clean up, can't be called multiple times safely due to
* the use of static variables.
*
* @param string $pid
* 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) {
// Before executing the query, we hve a base case of accessing the top-level collection
global $base_url;
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
static $max_level = 10;
static $level = -1;
@ -77,8 +95,10 @@ function islandora_get_breadcrumbs_recursive($pid, &$breadcrumbs, $repository) {
islandora_get_breadcrumbs_recursive($parent, $breadcrumbs, $repository);
}
else {
$breadcrumbs[] = '...'; // Add an non-link, as we don't know how to get back to the root.
islandora_get_breadcrumbs_recursive($root, $breadcrumbs, $repository); // And render the last two links and break (on the next pass).
// Add an non-link, as we don't know how to get back to the root.
$breadcrumbs[] = '...';
// And render the last two links and break (on the next pass).
islandora_get_breadcrumbs_recursive($root, $breadcrumbs, $repository);
}
}
}

527
includes/datastream.inc

@ -2,492 +2,143 @@
/**
* @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.
*
* @global object $user
* @param string $object_id
* @param string $dsid
* @return stream
* prints datastream to browser
* @note
* This function calls exit().
*
* @param FedoraDatastream $datastream
* 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') {
// if the object exists but the datastream doesn't
if (!isset($object[$dsid])) {
return drupal_not_found();
}
function islandora_view_datastream(FedoraDatastream $datastream, $download = FALSE) {
header_remove('Cache-Control');
header_remove('Expires');
header('Content-type: ' . $object[$dsid]->mimetype);
if ($object[$dsid]->controlGroup == 'M' || $object[$dsid]->controlGroup == 'X') {
header('Content-length: ' . $object[$dsid]->size);
header('Content-type: ' . $datastream->mimetype);
if ($datastream->controlGroup == 'M' || $datastream->controlGroup == 'X') {
header('Content-length: ' . $datastream->size);
}
if ($method == 'download') {
header("Content-Disposition: attachment; filename=\"" . $object[$dsid]->label);
if ($download) {
header("Content-Disposition: attachment; filename=\"{$datastream->label}\"");
}
// Disable page caching
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');
$object[$dsid]->getContent($file);
$datastream->getContent($file);
readfile($file);
drupal_unlink($file);
exit();
}
/**
* For a given object, return all parent collections.
*/
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;
}
/**
* Get the human readable size of the given datastream.
*
* @param array $arr
* an array of dsids that are defined by this objects cmodels
* @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;
}
}
}
/**
* @param FedoraDatastream $datastream
* The datastream to check.
*
* @global type $user
* @param string $object_id
* @return string|array
* @return string
* A human readable size of the given datastream, or '-' if the size could not
* be determined.
*/
function islandora_get_unused_dsids($object) {
$defined_dsids = array();
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;
function islandora_datastream_get_human_readable_size(FedoraDatastream $datastream) {
module_load_include('inc', 'islandora', 'includes/utilities');
$size_is_calculatable = $datastream->controlGroup == 'M' || $datastream->controlGroup == 'X';
return $size_is_calculatable ? islandora_convert_bytes_to_human_readable($datastream->size) : '-';
}
/**
* 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
* Get either the 'view' or 'download' url for the given datastream if possible.
*
* @param FedoraDatastream $datastream
* The datastream to generated the url to.
*
* @return string
* either the 'view' or 'download' url for the given datastream.
*/
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;
function islandora_datastream_get_url(FedoraDatastream $datastream, $type = 'download') {
return $datastream->controlGroup == 'R' ? $datastream->url : "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/$type";
}
/**
* 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
* Gets the delete link.
*
* @param FedoraDatastream $datastream
* The datastream to generated the url to.
*/
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");
function islandora_datastream_get_delete_link(FedoraDatastream $datastream) {
$datastreams = module_invoke_all('islandora_undeletable_datastreams', $datastream->parent->models);
$can_delete = !in_array($datastream->id, $datastreams);
return $can_delete ? l(t('delete'), "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/delete") : '';
}
/**
* validates this datastream id against its allowed mimetypes in the dscomposite
* of its content models.
* @param array $form
* @param array $form_state
* @return boolean
* Gets the edit link.
*
* @param FedoraDatastream $datastream
* The datastream to generated the url to.
*/
function islandora_add_datastream_form_validate($form, &$form_state) {
module_load_include('inc', 'islandora', 'includes/mime.detect');
$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();
function islandora_datastream_edit_get_link(FedoraDatastream $datastream) {
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $datastream->parent, $datastream);
$can_edit = count($edit_registry) > 0 && user_access(FEDORA_METADATA_EDIT);
return $can_edit ? l(t('edit'), "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/edit") : '';
}
$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
* @param string $object_id
* @param array $form_state
* @return array
* a form ready to be rendered with a call to Drupal render
* Display the edit datastream page.
*
* @param FedoraDatastream $datastream
* The datastream to edit.
*/
function islandora_add_datastream_form($form, &$form_state, $object) {
// Ensure we're loaded, in case AJAX stuff is ever added.
form_load_include($form_state, 'inc', 'islandora', 'includes/datastream');
$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 '';
}
else {
return l(t('delete'), 'islandora/object/' . $ds->parent->id . '/datastream/' . $ds->id . '/delete');
}
}
function islandora_islandora_undeletable_datastreams($models) {
return array('DC');
}
function islandora_datastream_edit_get_link($object, $ds_id) {
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $object, $ds_id);
if (count($edit_registry) > 0 && user_access(FEDORA_METADATA_EDIT)) {
return l(t('edit'), 'islandora/object/' . $object->id . '/datastream/' . $ds_id . '/edit');
}
else {
return '';
}
}
function islandora_edit_datastream($object, $ds_id) {
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $object, $ds_id);
function islandora_edit_datastream(FedoraDatastream $datastream) {
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $datastream->parent, $datastream);
$edit_count = count($edit_registry);
if ($edit_count == 0) {
switch ($edit_count) {
case 0:
// No edit implementations.
drupal_set_message(t('There are no edit methods specified for this datastream.'));
drupal_goto('islandora/object/' . $object->id . '/manage/datastreams');
}
elseif ($edit_count == 1) {
drupal_goto("islandora/object/{$object->id}/manage/datastreams");
break;
case 1:
// One registry implementation, go there
drupal_goto($edit_registry[0]['url']);
}
else {
break;
default:
// Multiple edit routes registered
return islandora_edit_datastream_registry_render($edit_registry);
}
}
// @TODO: theme / preprocess
function islandora_edit_datastream_registry_render($edit_registry) {
$output = array(
/**
* Displays links to all the edit datastream registry items.
*
* @param array $edit_registry
* A list of 'islandora_edit_datastream_registry' values.
*/
function islandora_edit_datastream_registry_render(array $edit_registry) {
$markup = '';
foreach ($edit_registry as $edit_route) {
$markup .= l($edit_route['name'], $edit_route['url']) . '<br/>';
}
return array(
'#type' => 'markup',
'#markup' => '',
'#markup' => $markup,
);
foreach ($edit_registry AS $edit_route) {
$output['#markup'] .= l($edit_route['name'], $edit_route['url']) . '<br/>';
}
return $output;
}

66
includes/delete_datastream.form.inc

@ -0,0 +1,66 @@
<?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 islandora_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}";
}

50
includes/delete_object.form.inc

@ -0,0 +1,50 @@
<?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')
);
}
/**
* Delete's the object in questionGives deloption of deleting or purging and object.
*
* @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');
module_load_include('inc', 'islandora', 'includes/utilities');
$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);
}

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;
}

428
includes/ingest.form.inc

@ -0,0 +1,428 @@
<?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
* An associative array of configuration values that are used to build the
* list of steps to be executed, including:
* - id: The PID with which the object should be created.
* - namespace: The PID namespace in which the object should be created.
* (id is used first, if it is given).
* - label: The initial label for the object. Defaults to "New Object".
* - collections: An array of collection PIDs, to which the new object should
* be related.
* - models: An array of content model PIDs, to which the new object should
* subscribe
*
* @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) {
// First time initialization of storage.
islandora_ingest_form_init_form_state_storage($form_state, $configuration);
$steps = &islandora_ingest_form_get_steps($form_state);
// Always re-sort the steps just incase any build/submit handlers have
// appended new steps.
usort($steps, 'drupal_sort_weight');
// Load any required files for the current step.
islandora_ingest_form_step_form_load_include($form_state);
}
/**
* 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) {
module_load_include('inc', 'islandora', 'includes/utilities');
if (empty($form_state['islandora'])) {
// Use ID if given.
$id = isset($configuration['id']) ? $configuration['id'] : NULL;
// Use namespace if ID not given.
$namespace = isset($configuration['namespace']) && !isset($id) ? $configuration['namespace'] : $id;
$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'];
$step--;
$step_info = &islandora_ingest_form_get_step_info($form_state, $step);
$form_state['values'] = isset($step_info['values']) ? $step_info['values'] : NULL;
$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'];
$step++;
$step_info = &islandora_ingest_form_get_step_info($form_state, $step);
$form_state['values'] = isset($step_info['values']) ? $step_info['values'] : array();
$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);
$form_state['redirect'] = "islandora/object/{$object->id}";
} catch (Exception $e) {
// If post hooks throws it may already exist at this point but may be invalid, so don't say failed :P
watchdog('islandora', $e->getMessage(), NULL, WATCHDOG_ERROR);
drupal_set_message(t('A problem occured while ingesting "@label" (ID: @pid), please notifiy the administrator.', array('@label' => $object->label, '@pid' => $object->id)), 'error');
}
}
}
/**
* Gets the configuration used to create the multi-page ingest form.
*
* @param array $form_state
* The drupal form state.
*
* @return array
* The configuration used to generate the multi-page ingest forms.
*/
function islandora_ingest_form_get_configuration(array $form_state) {
return $form_state['islandora']['configuration'];
}
/**
* Gets a reference to the stored NewFedoraObject's which are to be ingested
* when the final step submits.
*
* @param array $form_state
* The drupal form state.
*
* @return array
* A reference to the stored NewFedoraObjects to be ingested when the final
* step submits.
*/
function &islandora_ingest_form_get_objects(array $form_state) {
return $form_state['islandora']['objects'];
}
/**
* Gets a single object from the stored NewFedoraObject's.
*
* @note - In our current use case we are only dealing with a single object
* ingest, this makes it convenient to access it. Ideally the steps
* implementations will be abstracted to be indifferent to what object it's
* currently working on. This will act as a placeholder for such
* functionality.
*
* @param array $form_state
* The drupal form state.
*
* @return array
* Returns the 'current' object in the array of NewFedoraObjects, generally
* this is only used when there is one object in the list of objects.
*/
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];
}
// @todo deal with unknown case.
return NULL;
}
/**
* 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');
$step_info = islandora_ingest_form_get_step_info($form_state);
// Load include files
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);
}
}
/**
* 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));
}
// Remove NULL values.
$steps = array_filter($steps);
usort($steps, 'drupal_sort_weight');
return $steps;
}

66
includes/ingest.menu.inc

@ -0,0 +1,66 @@
<?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) {
drupal_set_message(t('Invalid ingest configuration.'), 'error');
$redirect = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '<front>';
// Redirect back to referer or top level collection.
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']);
}

237
includes/islandora.ingest.inc

@ -1,237 +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) {
drupal_alter('islandora_pre_ingest', $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);
}

120
includes/object_properties.form.inc

@ -0,0 +1,120 @@
<?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'),
// Double the normal length
'#size' => 120,
// Max length for a Fedora Label
'#maxlength' => 255,
'#type' => 'textfield'
),
// @todo Make this into an autocomplete field that list the users in the
// system as well.
'object_owner' => array(
'#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);
}

181
includes/solution_packs.inc

@ -2,29 +2,25 @@
/**
* @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() {
// add css
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
// check connection
module_load_include('inc', 'islandora', 'includes/utilities');
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora');
$info = islandora_describe_repository($url);
if (!$info) {
$config_url = url('admin/islandora/configure');
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');
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
if (!islandora_describe_repository()) {
$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' => url('admin/islandora/configure')));
drupal_set_message($message, 'error');
}
// set variables
$enabled_solution_packs = module_invoke_all('islandora_required_objects');
$output = '';
foreach ($enabled_solution_packs as $solution_pack_module => $solution_pack_info) {
$objects = array();
foreach ($solution_pack_info as $field => $value) {
@ -37,12 +33,9 @@ function islandora_solution_packs_admin() {
break;
}
}
// get form
$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);
}
return $output;
}
@ -50,10 +43,7 @@ function islandora_solution_packs_admin() {
* Solution pack admin page
*/
function islandora_solution_pack_form($form, &$form_state, $solution_pack_module, $solution_pack_name, $objects = array()) {
// set variables
global $base_url;
global $base_path;
$needs_update = FALSE;
$needs_install = FALSE;
$could_not_connect = FALSE;
@ -80,25 +70,15 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
'#value' => $objects,
);
// table
// header
$table_header = array(t('Label'), t('PID'), t('Status'));
$table_rows = array();
// loop over defined objects
foreach ($objects as $object) {
$datastreams = NULL;
if (isset($object['pid'])) {
// set variables
$pid = $object['pid'];
// table row
$table_row = array();
// check object status
$object_status = islandora_check_object_status($object);
// set status labels
switch ($object_status) {
case 'up_to_date':
$object_status = t('Up-to-date');
@ -120,8 +100,6 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
$could_not_connect = TRUE;
break;
}
// label
if ($needs_install OR $could_not_connect) {
$label = $object['label'] ? $object['label'] : '';
}
@ -129,11 +107,8 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
$label = $object['label'] ? l($object['label'], $base_url . '/islandora/object/' . $pid) : '';
}
$table_row[] = $label;
// pid
$table_row[] = $pid;
// object status
$table_row[] = $object_status;
// add row
$table_rows[] = $table_row;
}
}
@ -146,7 +121,6 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
'#suffix' => '</h3>',
);
// install status
$form['solution_pack']['install_status'] = array(
'#markup' => '<strong>' . t('Object status:') . '&nbsp;</strong>',
'#prefix' => '<div class="islandora-solution-pack-install-status">',
@ -169,14 +143,12 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
$submit_button_text = '';
}
// table
$form['solution_pack']['table'] = array(
'#type' => 'item',
'#markup' => theme('table', array('header' => $table_header, 'rows' => $table_rows)),
);
}
// submit
if (!$could_not_connect) {
$form['solution_pack']['submit'] = array(
'#value' => $submit_button_text,
@ -185,12 +157,8 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
'#attributes' => array('class' => array('islandora-solution-pack-submit')),
'#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;
}
@ -203,8 +171,6 @@ function islandora_solution_pack_form($form, &$form_state, $solution_pack_modul
* The state of the form submited.
*/
function islandora_solution_pack_form_submit($form, &$form_state) {
// get variables
$solution_pack_module = $form_state['values']['solution_pack_module'];
$solution_pack_name = $form_state['values']['solution_pack_name'];
$objects = $form_state['values']['objects'];
@ -228,22 +194,16 @@ function islandora_solution_pack_form_submit($form, &$form_state) {
}
/**
* Batch reingest object(s)
*
* @param type $object
* @param array $object
* @param type $context
* @return type
*/
function islandora_batch_reingest_object($object_model, &$context) {
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 $base_url;
// new connection
@ -256,9 +216,8 @@ function islandora_batch_reingest_object($object_model, &$context) {
}
if (!empty($object_model) && is_array($object_model)) {
// set and validate PID
$pid = $object_model['pid'];
if (!islandora_validate_pid($pid)) {
if (!islandora_is_valid_pid($pid)) {
return NULL;
}
@ -267,13 +226,16 @@ function islandora_batch_reingest_object($object_model, &$context) {
$object_query = $connection->api->a->findObjects('query', 'pid=' . $pid);
$reinstall = FALSE;
if (!empty($object_query['results'])) {
islandora_object_purge($pid);
$object = islandora_object_load($pid);
if (isset($object)) {
islandora_delete_object($object);
}
$reinstall = TRUE;
}
// build and ingest new object
try {
$object = islandora_ingest_new_object($object_model);
$object = islandora_solution_pack_add_object($object_model);
$object_name = $object->label;
if ($reinstall) {
drupal_set_message(t('Successfully reinstalled <em>@object_name</em>.', array('@object_name' => $object_name, '@pid' => $pid)));
@ -297,11 +259,7 @@ function islandora_batch_reingest_object($object_model, &$context) {
function islandora_install_solution_pack($module_name = NULL, $op = 'install') {
// check if a module name is given. // @TODO: check module name for existance
if (!empty($module_name)) {
// include files
module_load_include('inc', 'islandora', 'includes/tuque');
module_load_include('module', 'islandora', 'islandora');
module_load_include('inc', 'islandora', 'includes/islandora.ingest');
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('module', $module_name, $module_name);
@ -381,9 +339,7 @@ function islandora_install_solution_pack($module_name = NULL, $op = 'install') {
}
}
else {
// build and ingest new object
islandora_ingest_new_object($object);
// set message
islandora_solution_pack_add_object($object);
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;
@ -414,7 +370,8 @@ function islandora_install_solution_pack($module_name = NULL, $op = 'install') {
*
* @see islandora_solution_pack_form()
* @see islandora_install_solution_pack()
* @TODO: should this function live in islandora.module so it can be called easier without having to include the solution_packs.inc file?
* @todo: Should this function live in islandora.module so it can be called
* easier without having to include the solution_packs.inc file?
*/
function islandora_check_object_status($object_model = array()) {
if (!empty($object_model)) {
@ -441,7 +398,8 @@ function islandora_check_object_status($object_model = array()) {
$object_status = 'missing';
}
else {
// object defined with single datastream file // @TODO: should dsversion be mandatory for the check to valid?
// object defined with single datastream file
// @TODO: should dsversion be mandatory for the check to valid?
if (isset($object_model['dsid']) && isset($object_model['datastream_file']) && isset($object_model['dsversion'])) {
$datastreams = array(
array(
@ -485,6 +443,88 @@ 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) {
module_load_include('inc', 'islandora', 'includes/utilities');
$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
* @{
@ -531,7 +571,9 @@ function islandora_viewers_form($variable_id = NULL, $mimetype = NULL) {
'#type' => 'item',
'#title' => t('Select a viewer'),
'#description' => t('Preferred viewer for your solution pack. These may be provided by third-party modules.'),
'#tree' => TRUE, // this attribute is important to return the submitted values in a deeper nested arrays in
// This attribute is important to return the submitted values in a deeper
// nested arrays in
'#tree' => TRUE,
'#theme' => 'islandora_viewers_table',
);
@ -582,7 +624,8 @@ function islandora_viewers_form($variable_id = NULL, $mimetype = NULL) {
* Returns all defined viewers.
*
* @param string $mimetype
* specify a mimetype to return only viewers that support this certain mimetype.
* specify a mimetype to return only viewers that support this certain
* mimetype.
* @return
* array of viewer definitions, or FALSE if none are found.
*/
@ -702,10 +745,8 @@ function islandora_get_viewer_id($variable_id) {
*/
function islandora_get_viewer_callback($viewer_id = NULL) {
if ($viewer_id !== NULL) {
// get defined viewers
$viewers = module_invoke_all('islandora_viewer_info');
if (isset($viewers[$viewer_id]['callback'])) {
// return callback function
return $viewers[$viewer_id]['callback'];
}
}

307
includes/utilities.inc

@ -3,6 +3,8 @@
/**
* @file
* Contains islandora utility functions
*
* @todo this file should be broken out into other files.
*/
/**
@ -58,45 +60,44 @@ function islandora_control_group_to_human_readable($control_group) {
}
/**
* valid pid ??
* @param type $pid
* Checks if the given pid is valid.
*
* @param string $pid
* The object id to check.
*
* @return boolean
* TRUE if valid, FALSE otherwise.
*/
function islandora_validate_pid($pid) {
$valid = FALSE;
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;
function islandora_is_valid_pid($pid) {
return drupal_strlen(trim($pid)) <= 64 && preg_match('/^([A-Za-z0-9]|-|\.)+:(([A-Za-z0-9])|-|\.|~|_|(%[0-9A-F]{2}))+$/', trim($pid));
}
/**
* Valid Dsid ??
* @param type $dsid
* Checks if the given datastream id is valid.
*
* @param string $dsid
* The datastream id to check.
*
* @return boolean
* TRUE if valid, FALSE otherwise.
*/
function islandora_validate_dsid($dsid) {
$valid = FALSE;
if (drupal_strlen(trim($dsid)) <= 64 && preg_match('/^[a-zA-Z0-9\_\-\.]+$/', trim($dsid))) {
$valid = TRUE;
}
return $valid;
function islandora_is_valid_dsid($dsid) {
return drupal_strlen(trim($dsid)) <= 64 && preg_match('/^[a-zA-Z0-9\_\-\.]+$/', trim($dsid));
}
/* Helper function to describe a Fedora repository.
/**
* Helper function to describe a Fedora repository.
*
* Can be used to check if Fedora is available.
*
* @param $url
* A url to a Fedora repository.
* @param string $url
* A url to a Fedora repository, if NULL the default is used.
* @return
* Returns an array describing the repository. Returns FALSE if Fedora is down
* or if the url is incorrect.
*/
function islandora_describe_repository($url) {
module_load_include('inc', 'islandora', 'includes/tuque');
function islandora_describe_repository($url = NULL) {
$url = isset($url) ? $url : variable_get('islandora_base_url', 'http://localhost:8080/fedora');
$connection = new IslandoraTuque(NULL, $url);
try {
$info = $connection->api->a->describeRepository();
@ -125,8 +126,9 @@ function islandora_describe_repository($url) {
function islandora_build_hook_list($hook, $pids = array()) {
$hooks = array();
foreach ($pids as $model) {
$hooks[] = islandora_escape_pid_for_function($model) . '_' . $hook;
$pids = array_unique($pids);
foreach ($pids as $pid) {
$hooks[] = islandora_escape_pid_for_function($pid) . '_' . $hook;
}
$hooks[] = $hook;
@ -152,3 +154,258 @@ function islandora_escape_pid_for_function($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 islandora_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;
}
/**
* 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) {
// @todo some logging would be nice, not sure what this throws.
return array();
}
$collections = array_map(function($o) { return islandora_object_load($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) {
module_load_include('inc', 'islandora', 'includes/utilities');
$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) {
return islandora_get_datastreams_requirements_from_models($object->models);
}
/**
* Get the list of which datastreams are valid in the given set of models.
*
* @param array $models
* An array of content models PIDs from which to parse the DS-COMPOSITE-MODEL
* stream.
*
* @return array
* An associative array of associative arrays, merged from calls to
* islandora_get_datastreams_requirements_from_content_model().
*/
function islandora_get_datastreams_requirements_from_models(array $models) {
$dsids = array();
foreach ($models as $model) {
$model = islandora_object_load($model);
$dsids += islandora_get_datastreams_requirements_from_content_model($model);
}
// The AUDIT Datastream can not really be added, so it can't really be missing.
unset($dsids['AUDIT']);
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()) {
module_load_include('inc', 'islandora', 'includes/IslandoraTuque');
global $user;
$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';
// Default 'Managed'
$control_group = (isset($ds['control_group']) && in_array($ds['control_group'], array('X', 'M', 'R', 'E'))) ? $ds['control_group'] : 'M';
$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;
}

46
islandora.api.php

@ -155,17 +155,15 @@ function hook_islandora_object_alter($fedora_object) {}
*
* @param type $islandora_object
* 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.
*
* @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.
@ -218,3 +216,43 @@ function hook_islandora_required_objects() {}
* @see islandora_get_viewer_callback()
*/
function hook_islandora_viewer_info() {}
/**
* Returns a list of datastreams that are determined to be undeletable.
*/
function hook_islandora_undeletable_datastreams(array $models) {}
/**
* Define steps used in the islandora_ingest_form() ingest process.
*
* @return array
* An array of associative arrays which define each step in the ingest
* process. Steps are defined by by a number of properties (keys) including:
* - type: The type of step. Currently, only "form" is implemented.
* - weight: The "weight" of this step--heavier(/"larger") values sink to the
* end of the process while smaller(/"lighter") values are executed first.
* - form_id: The form building function to call to get the form structure
* for this step.
* - args: An array of arguments to pass to the form building function.
* And may optionally include both:
* - module: A module from which we want to load an include.
* - file: A file to include (relative to the module's path, including the
* file's extension).
*/
function hook_islandora_ingest_steps(array $configuration) {
return array(
array(
'type' => 'form',
'weight' => 1,
'form_id' => 'my_cool_form',
'args' => array('arg_one', 'numero deux'),
),
);
}
/**
* Content model specific version of hook_islandora_ingest_steps().
*
* @see hook_islandora_ingest_steps()
*/
function hook_CMODEL_PID_islandora_ingest_steps(array $configuration) {}

3
islandora.info

@ -6,4 +6,7 @@ core = 7.x
configure = admin/islandora/configure
stylesheets[all][] = css/islandora.base.css
stylesheets[all][] = css/islandora.theme.css
files[] = includes/MimeDetect.inc
files[] = includes/DublinCore.inc
files[] = includes/IslandoraTuque.inc
php = 5.3

5
islandora.install

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

645
islandora.module

@ -1,9 +1,10 @@
<?php
/*
/**
* @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.
*
* This file is part of Islandora.
*
@ -21,6 +22,8 @@
* along with the program. If not, see <http ://www.gnu.org/licenses/>.
*/
// Common datastreams
define('DS_COMP_STREAM', 'DS-COMPOSITE-MODEL');
// Permissions
define('FEDORA_VIEW', 'view fedora repository');
@ -34,16 +37,23 @@ define('FEDORA_MANAGE', 'manage fedora items');
// Hooks
define('ISLANDORA_VIEW_HOOK', 'islandora_view_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_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');
define('ISLANDORA_EDIT_DATASTREAM_HOOK', 'islandora_edit_datastream');
/**
* 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() {
$items = array();
$items['admin/islandora'] = array(
'title' => 'Islandora',
'description' => "Configure settings associated with Islandora.",
@ -60,7 +70,6 @@ function islandora_menu() {
'type' => MENU_NORMAL_ITEM,
'weight' => -1,
);
$items['admin/islandora/solution_packs'] = array(
'title' => 'Solution packs',
'description' => 'Install content models and collections required by installed solution packs.',
@ -69,146 +78,130 @@ function islandora_menu() {
'file' => 'includes/solution_packs.inc',
'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(
'title' => 'Islandora Repository',
'page callback' => 'islandora_view_default_object',
'type' => MENU_NORMAL_ITEM,
'access arguments' => array(FEDORA_VIEW),
);
$items['islandora/object/%islandora_object'] = array(
'title' => 'Repository',
'page callback' => 'islandora_view_object',
'page arguments' => array(2),
'type' => MENU_NORMAL_ITEM,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_VIEW),
'access callback' => 'islandora_object_access_callback',
'access arguments' => array(FEDORA_VIEW, 2),
);
$items['islandora/object/%islandora_object/view'] = array(
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -1,
);
$items['islandora/object/%islandora_object/view/default'] = array(
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -1,
);
$items['islandora/object/%islandora_object/manage'] = array(
'title' => 'Manage',
'page callback' => 'islandora_edit_object',
'page arguments' => array(2),
'type' => MENU_LOCAL_TASK,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_MODIFY_STATE),
'access callback' => 'islandora_object_access_callback',
'access arguments' => array(FEDORA_MODIFY_STATE, 2),
);
$items['islandora/object/%islandora_object/manage/datastreams'] = array(
'title' => 'Datastreams',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['islandora/object/%islandora_object/manage/properties'] = array(
'title' => 'Properties',
'page callback' => 'drupal_get_form',
'file' => 'includes/object_properties.inc',
'page arguments' => array('islandora_edit_properties_form', 2),
'file' => 'includes/object_properties.form.inc',
'page arguments' => array('islandora_object_properties_form', 2),
'type' => MENU_LOCAL_TASK,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_MODIFY_STATE),
'access callback' => 'islandora_object_access_callback',
'access arguments' => array(FEDORA_MODIFY_STATE, 2),
'weight' => -5,
);
$items['islandora/object/%islandora_object/delete'] = array(
'title' => 'Delete object',
'file' => 'includes/purge.form.inc',
'file' => 'includes/delete_object.form.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array('islandora_purge_object', 2),
'page arguments' => array('islandora_delete_object_form', 2),
'type' => MENU_CALLBACK,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_PURGE),
'access callback' => 'islandora_object_access_callback',
'access arguments' => array(FEDORA_PURGE, 2),
);
$items['islandora/object/%islandora_object/manage/datastreams/add'] = array(
'title' => 'Add a datastream',
'file' => 'includes/datastream.inc',
'file' => 'includes/add_datastream.form.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array('islandora_add_datastream_form', 2),
'type' => MENU_LOCAL_ACTION,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_ADD_DS)
'access callback' => 'islandora_object_access_callback',
'access arguments' => array(FEDORA_ADD_DS, 2)
);
$items['islandora/object/%islandora_object/manage/datastreams/add/autocomplete'] = array(
'file' => 'includes/datastream.inc',
'page callback' => 'islandora_datastream_autocomplete_callback',
'file' => 'includes/add_datastream.form.inc',
'page callback' => 'islandora_add_datastream_form_autocomplete_callback',
'page arguments' => array(2),
'type' => MENU_CALLBACK,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_ADD_DS)
'access callback' => 'islandora_object_access_callback',
'access arguments' => array(FEDORA_ADD_DS, 2)
);
$items['islandora/object/%islandora_object/datastream/%'] = array(
$items['islandora/object/%islandora_object/datastream/%islandora_datastream'] = array(
'title' => 'View datastream',
'page callback' => 'islandora_view_datastream',
'page arguments' => array(2, 4),
'page arguments' => array(4, FALSE),
'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc',
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_VIEW),
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_VIEW, 2, 4),
'load arguments' => array(2),
);
$items['islandora/object/%islandora_object/datastream/%/view'] = array(
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/view'] = array(
'title' => 'View datastream',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['islandora/object/%islandora_object/datastream/%/download'] = array(
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/download'] = array(
'title' => 'Download datastream',
'page callback' => 'islandora_view_datastream',
'page arguments' => array(2, 4, 5),
'page callback' => 'islandora_download_datastream',
'page arguments' => array(4),
'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc',
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_VIEW),
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_VIEW, 2, 4),
'load arguments' => array(2),
);
$items['islandora/object/%islandora_object/datastream/%/edit'] = array(
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/edit'] = array(
'title' => 'Edit datastream',
'page callback' => 'islandora_edit_datastream',
'page arguments' => array(2, 4),
'page arguments' => array(4),
'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc',
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_METADATA_EDIT),
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_METADATA_EDIT, 2, 4),
'load arguments' => array(2),
);
$items['islandora/object/%islandora_object/datastream/%/delete'] = array(
'title' => 'Purge data stream',
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/delete'] = array(
'title' => 'Delete data stream',
'page callback' => 'drupal_get_form',
'page arguments' => array('islandora_purge_datastream', 2, 4),
'file' => 'includes/purge.form.inc',
'page arguments' => array('islandora_delete_datastream_form', 4),
'file' => 'includes/delete_datastream.form.inc',
'type' => MENU_CALLBACK,
'access callback' => 'islandora_access_callback',
'access arguments' => array(2, FEDORA_PURGE),
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_PURGE, 2, 4),
'load arguments' => array(2),
);
$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;
}
@ -225,8 +218,6 @@ function islandora_admin_paths() {
/**
* Implements hook_theme().
*
* @return array
*/
function islandora_theme() {
return array(
@ -252,8 +243,6 @@ function islandora_theme() {
/**
* Implements hook_permission().
*
* @return array
*/
function islandora_permission() {
return array(
@ -302,97 +291,101 @@ function islandora_forms($form_id) {
}
/**
* determines whether we can see the object or not
* checks PID namespace permissions, and user permissions
* @global object $user
* @param string $op
* @param string $pid
* Checks whether the user can access the given object 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.
*
* @return boolean
* TRUE if the user is allowed to access this object, FALSE otherwise.
*/
function islandora_access_callback($object = NULL, $perm = NULL) {
if (!$object || !$perm) {
return FALSE;
}
$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);
function islandora_object_access_callback($perm, $object = NULL) {
module_load_include('inc', 'islandora', 'includes/utilities');
return user_access($perm) && is_object($object) && islandora_namespace_accessible($object->id);
}
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) && islandora_namespace_accessible($object->id) && is_object($datastream);
}
/**
* a function to call other modules edit page. If there are not any modules
* that handle this function this module will build a default page.
* @global object $user
* @param string $object_id
* Renders the given objects manage page.
*
* Its possible to modify the output of this function if 'ISLANDORA_EDIT_HOOK'
* is implemented in other modules.
*
* If no modules implement 'ISLANDORA_EDIT_HOOK' then this function returns the
* default manage view.
*
* @param FedoraObject $object
* The object to manage.
*
* @return string
* The HTML repersentation of the manage object page.
*/
function islandora_edit_object($object) {
if (!$object) {
return drupal_not_found();
}
function islandora_edit_object(FedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
// Accumulate the output.
$output = array();
// Call cmodel oriented variants first.
foreach (islandora_build_hook_list(ISLANDORA_EDIT_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
}
}
// Add in the default, if we did not get any results.
if (empty($output)) {
// Add in the default, if we did not get any results.
$output = islandora_default_islandora_edit_object($object);
}
arsort($output);
drupal_alter(ISLANDORA_EDIT_HOOK, $object, $output);
return implode('', $output);
}
/**
* edit properties form
* @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.
* Renders the default manage object page for the given object.
*
* @param object $fedora_object
* A tuque Fedora Object
* @param FedoraObject $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) {
$output = theme('islandora_default_edit', array(
'islandora_object' => $fedora_object,
));
function islandora_default_islandora_edit_object(FedoraObject $object) {
$output = theme('islandora_default_edit', array('islandora_object' => $object));
return array('Default Edit output' => $output);
}
@ -400,7 +393,7 @@ function islandora_default_islandora_edit_object($fedora_object) {
* Page callback for the path "islandora".
*
* Redirects to the view of the object indicated by the Drupal variable
* islandora_repository_pid.
* 'islandora_repository_pid'.
*/
function islandora_view_default_object() {
$pid = variable_get('islandora_repository_pid', 'islandora:root');
@ -408,59 +401,53 @@ function islandora_view_default_object() {
}
/**
* The view entry point. modules should implement hook_islandora_view_object for the Fedora Content models that
* their modules want to provide a view for.
* @global object $user
* @param string $object_id
* 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.
*
* If no modules implement the hook then the default view object page
* will be rendered.
*
* @param FedoraObject $object
* The object to view.
*
* @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/utilities');
global $user;
if (!$fedora_object) {
return drupal_not_found();
}
// set breadcrumbs
drupal_set_breadcrumb(islandora_get_breadcrumbs($fedora_object));
// optional pager parameters
drupal_set_breadcrumb(islandora_get_breadcrumbs($object));
// Optional pager parameters
$page_number = (empty($_GET['page'])) ? '1' : $_GET['page'];
$page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize'];
// Accumulate the output.
$output = array();
// Call cmodel oriented variants first.
foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $fedora_object->models) as $hook) {
$temp = module_invoke_all($hook, $fedora_object, $page_number, $page_size);
foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $object->models) as $hook) {
// @todo Remove page number and size from this hook, implementers of the
// hook should use drupal page handling directly.
$temp = module_invoke_all($hook, $object, $page_number, $page_size);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
}
}
// Add in the default, if we did not get any results.
if (empty($output)) {
$output = islandora_default_islandora_view_object($fedora_object);
// No results, use the default view.
$output = islandora_default_islandora_view_object($object);
}
arsort($output);
drupal_alter(ISLANDORA_VIEW_HOOK, $fedora_object, $output);
drupal_alter(ISLANDORA_VIEW_HOOK, $object, $output);
return implode('', $output);
}
/**
* If there are no modules registered to handle this objects cmodels or there are
* not any cmodels specified this will create a default display.
* Renders the default view object page for the given object.
*
* @param FedoraObject $object
* The object whose display we are to render.
* The object used to render the view object page.
*
* @return array
* The default rendering of the object view page, indexed at 'Default output'.
*/
function islandora_default_islandora_view_object($object) {
$output = theme('islandora_default', array('islandora_object' => $object));
@ -468,111 +455,77 @@ 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'.
*
* @global object $user
* @param string $object_id
* The pid of an object in the menu path identified by '%islandora_object'.
*
* @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
* drupal_page_not_found().
* If the object was inaccessible then NULL is returned, and the
* access callback is expected to catch that case, triggering
* drupal_access_denied().
*/
function islandora_object_load($object_id) {
module_load_include('inc', 'islandora', 'includes/tuque');
$islandora_tuque = &drupal_static(__FUNCTION__);
if (!$islandora_tuque) {
$islandora_tuque = new IslandoraTuque();
}
if (IslandoraTuque::exists()) {
module_load_include('inc', 'islandora', 'includes/IslandoraTuque');
$tuque = islandora_get_tuque_connection();
if ($tuque) {
try {
$fedora_object = $islandora_tuque->repository->getObject($object_id);
$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;
}
drupal_alter('islandora_object', $fedora_object);
return $fedora_object;
}
}
else {
IslandoraTuque::getError();
return NULL;
}
// Assuming access denied in all other cases for now.
return NULL;
}
/**
* 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
* @param string $object_id
* @return FedoraObject
* Its up to the access callbacks and menu callbacks to trigger
* drupal_access_denied() when appropriate.
*
* @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'.
*
* $param string $object_id
* The object to load the datastream from.
*
* @return FedoraDatastream
* If the given datastream ID exists then this returns a FedoraDatastream
* object, otherwise it returns NULL which triggers drupal_page_not_found().
*/
function islandora_object_purge($object_id) {
if (!$object_id) {
drupal_set_message(t('Cannot remove object, object id not set'));
return;
}
// load object
function islandora_datastream_load($datastream_id, $object_id) {
$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 {
try {
$object->repository->purgeObject($object_id);
} catch (Exception $e) {
drupal_set_message(t('Error purging Islandora object %s %e', array('%s' => $object_id, '%e' => $e)), 'error');
return "";
}
}
module_invoke_all('islandora_post_purge_object', $object_id, $content_models); // notify modules post deletion
}
/**
* Ingest access callback
*/
function islandora_ingest_access_callback($object, $perm) {
if (islandora_access_callback($object, $perm) === FALSE) {
return FALSE;
return NULL;
}
$ingest_registry = module_invoke_all('islandora_ingest_registry', $object);
if (count($ingest_registry) > 0) {
return TRUE;
}
else {
return FALSE;
}
return $object[$datastream_id];
}
/**
* Content model, collection view and collection policy datastreams may now optionally define a version
* number in their top-level XML element as an attribute, as in:
* Content model, collection view and collection policy datastreams may now
* optionally define a version number in their top-level XML element as an
* attribute, as in:
* <content_model name="Collection" version="2" ...
*
* @param object $item
@ -602,7 +555,6 @@ function islandora_get_islandora_datastream_version($item = NULL, $dsid = NULL,
* Implements hook_islandora_required_objects().
*/
function islandora_islandora_required_objects() {
// module path
$module_path = drupal_get_path('module', 'islandora');
return array(
'islandora' => array(
@ -634,7 +586,202 @@ function islandora_islandora_required_objects() {
);
}
/**
* Implements islandora_undeleteable_datastreams().
*/
function islandora_islandora_undeletable_datastreams(array $models) {
return array('DC');
}
/**
* Ingest the given object into Fedora calling its pre/post hooks as well.
*
* @todo will be cleaned up in the future
*
* @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_id, $models);
return TRUE;
default:
// Purge
$object->repository->purgeObject($object_id);
islandora_post_delete_object($object_id, $models);
$object = NULL;
return TRUE;
}
}
/**
* 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_PURGE_OBJECT_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';
// @todo Differentiate between delete/purge in the hooks.
islandora_post_delete_datastream($object, $datastream_id);
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) {
// Not sure this will work the greatest, probably an alter would be better..
$results = array_merge_recursive($results, module_invoke_all($hook, $datastream));
}
$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);
}
}

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

@ -2,8 +2,9 @@
/**
* @file
* islandora-object-edit.tpl.php: This is a template for objects that do not have
* a module to registered to build their display.
*
* islandora-object-edit.tpl.php: This is a template for objects that do not
* have a module to registered to build their display.
*
* islandora_object is a fedora tuque Object
* $object->label
@ -11,9 +12,10 @@
* to get the contents of a datastream
* $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
* 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.
*
*/

21
theme/islandora-object.tpl.php

@ -1,8 +1,10 @@
<?php
/*
/**
* @file
* This is a template for objects that do not have a module to registered to build their display.
*
* This is a template for objects that do not have a module to registered to
* build their display.
*
* islandora_object is a fedora tuque Object
* $object->label - The label for this object.
@ -35,13 +37,16 @@
* $ds->size - The size of the datastream
* $ds->checksum - The checksum of the datastream
* $ds->checksumType - The type of checksum for the datastream.
* $ds->createdDate->format("Y-m-d") - The created date with an option to use a format of your choice
* $ds->createdDate->format("Y-m-d") - The created date with an option to use
* a format of your choice
* $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
* 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.
*
*
@ -80,8 +85,8 @@
<?php if ($parent_collections): ?>
<dt>Collections</dt>
<dd>
<?php foreach ($parent_collections as $key => $value): ?>
<div><?php print $value['label_link'] ?></div>
<?php foreach ($parent_collections as $collection): ?>
<div><?php print l($collection->label, "islandora/object/{$collection->id}"); ?></div>
<?php endforeach; ?>
</dd>
<?php endif; ?>

13
theme/islandora.theme.inc

@ -2,6 +2,7 @@
/**
* @file
*
* This file contains all theme and preprocess functions.
*/
@ -13,13 +14,12 @@
* theme variables for the edit template
*/
function islandora_preprocess_islandora_default_edit(&$variables) {
$islandora_object = $variables['islandora_object'];
global $base_url;
$islandora_object = $variables['islandora_object'];
$datastreams = array();
$variables['islandora_editmetadata_url'] = $base_url . '/islandora/edit_form/' . $islandora_object->id;
module_load_include('inc', 'islandora', 'includes/datastream');
module_load_include('inc', 'islandora', 'includes/utilities');
// $variables['add_datastream_form'] = drupal_get_form('islandora_add_datastream_form', $islandora_object->id);
$header = array(
array('data' => t('ID')),
array('data' => t('Label')),
@ -27,7 +27,6 @@ function islandora_preprocess_islandora_default_edit(&$variables) {
array('data' => t('Mime type')),
array('data' => t('Size')),
array('data' => t('Operations'), 'colspan' => '3'),
//array('data' => t('Delete')),
);
$table_attributes = array('class' => array('manage-datastreams'));
$rows = array();
@ -39,7 +38,7 @@ function islandora_preprocess_islandora_default_edit(&$variables) {
array('class' => 'datastream-mime', 'data' => $ds->mimeType),
array('class' => 'datastream-size', 'data' => islandora_datastream_get_human_readable_size($ds)),
array('class' => 'datastream-download', 'data' => l(t('download'), islandora_datastream_get_url($ds, 'download'))),
array('class' => 'datstream-edit', 'data' => islandora_datastream_edit_get_link($islandora_object, $ds->id)),
array('class' => 'datstream-edit', 'data' => islandora_datastream_edit_get_link($ds)),
array('class' => 'datastream-delete', 'data' => islandora_datastream_get_delete_link($ds)),
);
}
@ -59,11 +58,10 @@ function islandora_preprocess_islandora_default(&$variables) {
drupal_add_js('misc/form.js');
drupal_add_js('misc/collapse.js');
$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/datastream');
$variables['parent_collections'] = islandora_datastream_get_parents($islandora_object);
$variables['parent_collections'] = islandora_get_parents_from_rels_ext($islandora_object);
$datastreams = array();
foreach ($islandora_object as $ds) {
@ -88,8 +86,7 @@ function islandora_preprocess_islandora_default(&$variables) {
$variables['datastreams'] = $datastreams;
try {
$dc = $islandora_object['DC']->content;
//$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();
} catch (Exception $e) {
drupal_set_message(t('Error retrieving object %s %t', array('%s' => $islandora_object->id, '%t' => $e->getMessage())), 'error', FALSE);

Loading…
Cancel
Save