Browse Source

Merge branch '7.x' of github.com:Islandora/islandora into 7.x-release

pull/384/head
jonathangreen 12 years ago
parent
commit
95c95b33bb
  1. 19
      .travis.yml
  2. 27
      README.md
  3. 164
      build.xml
  4. 3
      build/Doxyfile
  5. 39
      css/islandora.objects.css
  6. 12
      includes/add_datastream.form.inc
  7. 225
      includes/admin.form.inc
  8. 78
      includes/breadcrumb.inc
  9. 57
      includes/content_model.autocomplete.inc
  10. 84
      includes/datastream.inc
  11. 6
      includes/delete_datastream.form.inc
  12. 4
      includes/delete_object.form.inc
  13. 485
      includes/ingest.form.inc
  14. 49
      includes/ingest.menu.inc
  15. 18
      includes/mime_detect.inc
  16. 11
      includes/object_properties.form.inc
  17. 125
      includes/solution_packs.inc
  18. 26
      includes/tuque_wrapper.inc
  19. 263
      includes/utilities.inc
  20. 192
      islandora.api.php
  21. 4
      islandora.info
  22. 5
      islandora.install
  23. 491
      islandora.module
  24. 6
      islandora.rules.inc
  25. 3
      tests/README.md
  26. 149
      tests/hooked_access.test
  27. 12
      tests/hooks.test
  28. 118
      tests/ingest.test
  29. 7
      tests/islandora_hooked_access_test.info
  30. 31
      tests/islandora_hooked_access_test.module
  31. 3
      tests/islandora_hooks_test.info
  32. 14
      tests/islandora_hooks_test.module
  33. 7
      tests/islandora_ingest_test.info
  34. 166
      tests/islandora_ingest_test.module
  35. 114
      tests/islandora_manage_permissions.test
  36. 130
      tests/islandora_web_test_case.inc
  37. 14
      tests/scripts/line_endings.sh
  38. 40
      tests/scripts/travis_setup.sh
  39. 6
      tests/travis.test_config.ini
  40. 17
      theme/islandora-objects-grid.tpl.php
  41. 29
      theme/islandora-objects-list.tpl.php
  42. 21
      theme/islandora-objects.tpl.php
  43. 161
      theme/theme.inc

19
.travis.yml

@ -0,0 +1,19 @@
language: php
php:
- 5.3.3
- 5.4
branches:
only:
- 7.x
env:
- FEDORA_VERSION="3.5"
before_install:
- export ISLANDORA_DIR=$TRAVIS_BUILD_DIR
- $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh
- cd $HOME/drupal-*
script:
- ant -buildfile sites/all/modules/islandora/build.xml lint
- $ISLANDORA_DIR/tests/scripts/line_endings.sh sites/all/modules/islandora
- drush coder-review --reviews=production,security,style,i18n,potx,sniffer islandora
- phpcpd --names *.module,*.inc,*.test sites/all/modules/islandora
- drush test-run --uri=http://localhost:8081 Islandora

27
README.txt → README.md

@ -1,16 +1,10 @@
CONTENTS OF THIS FILE
---------------------
* summary
* requirements
* installation
* configuration
* customization
* troubleshooting
* faq
* contact
* sponsors
BUILD STATUS
------------
Current build status:
[![Build Status](https://travis-ci.org/Islandora/islandora.png?branch=7.x)](https://travis-ci.org/Islandora/islandora)
CI Server:
http://jenkins.discoverygarden.ca
SUMMARY
-------
@ -29,7 +23,11 @@ https://jira.duraspace.org/browse/ISLANDORA
REQUIREMENTS
------------
The Tuque library must be installed to use Islandora. It can be found here:
http://github.com/Islandora/tuque
It is expected to be in one of two paths:
- sites/all/libraries/tuque (libraries directory may need to be created)
- islandora_folder/libraries/tuque
INSTALLATION
------------
@ -41,7 +39,7 @@ should be copied into the Fedora global XACML policies folder. This will allow
CONFIGURATION
-------------
The islandora_drupal_filter passes the username of 'anonymous' through to
The islandora_drupal_filter passes the username of 'anonymous' through to
Fedora for unauthenticated Drupal Users. A user with the name of 'anonymous'
may have XACML policies applied to them that are meant to be applied to Drupal
users that are not logged in or vice-versa. This is a potential security issue
@ -53,6 +51,7 @@ Drupal's cron will can be ran to remove expired authentication tokens.
CUSTOMIZATION
-------------
[Customize ingest forms](http://github.com/Islandora/islandora/wiki/Multi-paged-Ingest-Forms)
TROUBLESHOOTING
---------------

164
build.xml

@ -1,110 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="islandora" default="build">
<target name="build"
depends="prepare,lint,doxygen,phploc,pdepend,phpcs-ci,phpcpd,phpcb"/>
<target name="build" depends="clean,prepare,lint,phploc,code_sniff,phpcpd,pdepend,doxygen,phpcb,test" />
<target name="clean" description="Cleanup build artifacts">
<delete dir="${basedir}/build/api"/>
<delete dir="${basedir}/build/code-browser"/>
<delete dir="${basedir}/build/coverage"/>
<delete dir="${basedir}/build/logs"/>
<delete dir="${basedir}/build/pdepend"/>
</target>
<target name="clean" description="Cleanup build artifacts">
<delete dir="${basedir}/build/test" />
<delete dir="${basedir}/build/logs" />
<delete dir="${basedir}/build/pdepend" />
<delete dir="${basedir}/build/api" />
<delete dir="${basedir}/build/code-browser" />
</target>
<target name="prepare" depends="clean"
description="Prepare for build">
<mkdir dir="${basedir}/build/api"/>
<mkdir dir="${basedir}/build/code-browser"/>
<mkdir dir="${basedir}/build/coverage"/>
<mkdir dir="${basedir}/build/logs"/>
<mkdir dir="${basedir}/build/pdepend"/>
</target>
<target name="prepare" description="Prepares workspace for artifacts" >
<mkdir dir="${basedir}/build/test" />
<mkdir dir="${basedir}/build/logs" />
<mkdir dir="${basedir}/build/pdepend" />
<mkdir dir="${basedir}/build/api" />
<mkdir dir="${basedir}/build/code-browser" />
</target>
<target name="lint">
<apply executable="php" failonerror="true">
<arg value="-l" />
<target name="lint" description="Perform syntax check of sourcecode files">
<apply executable="php" failonerror="true">
<arg value="-l" />
<fileset dir="${basedir}">
<include name="**/*.php" />
<modified />
</fileset>
</apply>
</target>
<fileset dir="${basedir}">
<include name="**/*.php" />
<include name="**/*.inc" />
<include name="**/*.module" />
<include name="**/*.install" />
<include name="**/*.test" />
<modified />
</fileset>
</apply>
</target>
<target name="phploc" description="Measure project size using PHPLOC">
<exec executable="phploc">
<arg value="--log-csv" />
<arg value="${basedir}/build/logs/phploc.csv" />
<arg path="${basedir}" />
</exec>
</target>
<target name="phploc" description="Measure project size using PHPLOC">
<exec executable="phploc">
<arg line="--log-csv ${basedir}/build/logs/phploc.csv --exclude build --exclude css --exclude images --exclude xml --names *.php,*.module,*.inc,*.test,*.install ${basedir}" />
</exec>
</target>
<target name="pdepend"
description="Calculate software metrics using PHP_Depend">
<exec executable="pdepend">
<arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
<arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
<arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
<arg path="${basedir}" />
</exec>
</target>
<target name="code_sniff" description="Checks the code for Drupal coding standard violations" >
<exec executable="phpcs">
<arg line="--standard=Drupal --report=checkstyle --report-file=${basedir}/build/logs/checkstyle.xml --extensions=php,inc,test,module,install --ignore=build/,xml/,images/,css/ ${basedir}" />
</exec>
</target>
<target name="phpcs"
description="Find coding standard violations using PHP_CodeSniffer and print human readable output. Intended for usage on the command line before committing.">
<exec executable="phpcs">
<arg value="--standard=Drupal" />
<arg value="--extensions=php" />
<arg value="--ignore=build/" />
<arg path="${basedir}" />
</exec>
</target>
<target name="phpcpd" description="Copy/Paste code detection">
<exec executable="phpcpd">
<arg line="--log-pmd ${basedir}/build/logs/pmd-cpd.xml --exclude build --exclude css --exclude images --exclude xml --names *.php,*.module,*.inc,*.test,*.install ${basedir}" />
</exec>
</target>
<target name="phpcs-ci"
description="Find coding standard violations using PHP_CodeSniffer creating a log file for the continuous integration server">
<exec executable="phpcs" output="/dev/null">
<arg value="--report=checkstyle" />
<arg value="--extensions=php" />
<arg value="--ignore=build/" />
<arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
<arg value="--standard=Drupal" />
<arg path="${basedir}" />
</exec>
</target>
<target name="pdepend" description="Calculate software metrics using PHP_Depend">
<exec executable="pdepend">
<arg line="--jdepend-xml=${basedir}/build/logs/jdepend.xml --jdepend-chart=${basedir}/build/pdepend/dependencies.svg --overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg ${basedir}"/>
</exec>
</target>
<target name="phpcpd" description="Find duplicate code using PHPCPD">
<exec executable="phpcpd">
<arg value="--log-pmd" />
<arg value="${basedir}/build/logs/pmd-cpd.xml" />
<arg path="${basedir}" />
</exec>
</target>
<target name="doxygen" description="Generate API documentation with doxygen" depends="prepare">
<exec executable="bash">
<arg line='-c "sed -i s/PROJECT_NUMBER\ \ \ \ \ \ \ \ \ =/PROJECT_NUMBER\ \ \ \ \ \ \ \ \ =\ `git log -1 --pretty=format:%h`/ build/Doxyfile"'/>
</exec>
<exec executable="doxygen">
<arg line="${basedir}/build/Doxyfile" />
</exec>
<exec executable="git">
<arg line="checkout ${basedir}/build/Doxyfile"/>
</exec>
</target>
<target name="doxygen" description="Generate API documentation with doxygen" depends="prepare">
<echo file="${basedir}/build/Doxyfile" append="true" message="PROJECT_NUMBER = "/>
<exec executable="git" output="${basedir}/build/Doxyfile" append="true">
<arg value="log" />
<arg value="-1" />
<arg value="--pretty=format:%h" />
</exec>
<exec executable="doxygen">
<arg path="${basedir}/build/Doxyfile" />
</exec>
<exec executable="git">
<arg value="checkout" />
<arg path="${basedir}/build/Doxyfile" />
</exec>
</target>
<target name="phpcb" description="Aggregate tool output with PHP_CodeBrowser">
<exec executable="phpcb">
<arg line="--log ${basedir}/build/logs --source ${basedir} --output ${basedir}/build/code-browser"/>
</exec>
</target>
<target name="phpcb"
description="Aggregate tool output with PHP_CodeBrowser">
<exec executable="phpcb">
<arg value="--log" />
<arg path="${basedir}/build/logs" />
<arg value="--source" />
<arg path="${basedir}" />
<arg value="--output" />
<arg path="${basedir}/build/code-browser" />
</exec>
</target>
<target name="test">
<exec executable="bash">
<arg line='-c "php ../../../../scripts/run-tests.sh --xml ${basedir}/build/test Islandora"' />
</exec>
</target>
</project>

3
build/Doxyfile

@ -27,6 +27,9 @@ DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = Islandora 7.x
# Put the git hash here using sed before generating the documentation.
PROJECT_NUMBER =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location

39
css/islandora.objects.css

@ -0,0 +1,39 @@
/**
* @file
* Styles for rendering grids/lists of objects.
*/
.islandora-objects-display-switch {
float: right;
}
.islandora-objects-grid-item {
display: inline-block;
width: 20%;
min-width: 100px;
min-height: 180px;
display: -moz-inline-stack;
display: inline-block;
vertical-align: top;
margin: 1.5em 1.84%;
zoom: 1;
*display: inline;
_height: 180px;
}
.islandora-objects-list-item {
padding-bottom: 1.5em;
border-bottom: 1px solid #ddd;
}
.islandora-objects-list-item .islandora-object-thumb {
clear: left;
float: left;
padding: 3px 0 0;
text-align: center;
width: 100px;
}
.islandora-objects-list-item .islandora-object-caption, .islandora-objects-list-item .islandora-object-description {
margin: 0 0 0 130px;
padding-top: 2px;
padding-bottom: 2px;
}
.islandora-object-thumb img {
width: 100%;
}

12
includes/add_datastream.form.inc

@ -12,13 +12,13 @@
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraObject $object
* @param AbstractObject $object
* The object to be deleted.
*
* @return array
* The drupal form definition.
*/
function islandora_add_datastream_form(array $form, array &$form_state, FedoraObject $object) {
function islandora_add_datastream_form(array $form, array &$form_state, AbstractObject $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');
@ -39,7 +39,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, FedoraOb
'#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)),
'#description' => t("An ID for this stream that is unique to this object. Must start with a letter and contain only alphanumeric characters, dashes and underscores. The following datastreams are defined by this content model but don't currently exist: <b>@unused_dsids</b>.", array('@unused_dsids' => $unused_datastreams)),
),
'#type' => 'textfield',
'#size' => 64,
@ -57,7 +57,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, FedoraOb
'#required' => TRUE,
'#size' => 64,
'#maxlength' => 64,
'#description' => t('A Human readable label'),
'#description' => t('A human-readable label'),
'#type' => 'textfield',
'#element_validate' => array('islandora_add_datastream_form_field_does_not_contain_a_forward_slash'),
),
@ -206,13 +206,13 @@ function islandora_add_datastream_form_submit(array $form, array &$form_state) {
*
* It lists the missing required (may be optional) datastreams.
*
* @param FedoraObject $object
* @param AbstractObject $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 = '') {
function islandora_add_datastream_form_autocomplete_callback(AbstractObject $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));

225
includes/admin.form.inc

@ -19,139 +19,111 @@
function islandora_repository_admin(array $form, array &$form_state) {
module_load_include('inc', 'islandora', 'includes/utilities');
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
$url = islandora_system_settings_form_default_value('islandora_base_url', 'http://localhost:8080/fedora', $form_state);
$restrict_namespaces = islandora_system_settings_form_default_value('islandora_namespace_restriction_enforced', FALSE, $form_state);
$confirmation_message = islandora_admin_settings_form_repository_access_message($url);
$form = array(
'islandora_tabs' => array(
'#type' => 'vertical_tabs',
'islandora_general' => array(
'#type' => 'fieldset',
'#title' => t('General Configuarion'),
'wrapper' => array(
'#prefix' => '<div id="islandora-url">',
'#suffix' => '</div>',
'#type' => 'markup',
'islandora_base_url' => array(
'#type' => 'textfield',
'#title' => t('Fedora base URL'),
'#default_value' => variable_get('islandora_base_url', 'http://localhost:8080/fedora'),
'#description' => t('The URL to use for REST connections <br/> !confirmation_message', array(
'!confirmation_message' => $confirmation_message)),
'#required' => TRUE,
'#ajax' => array(
'callback' => 'islandora_update_url_div',
'wrapper' => 'islandora-url',
'effect' => 'fade',
'event' => 'blur',
'progress' => array('type' => 'throbber'),
),
),
),
'islandora_repository_pid' => array(
'#type' => 'textfield',
'#title' => t('Root Collection PID'),
'#default_value' => variable_get('islandora_repository_pid', 'islandora:root'),
'#description' => t('The PID of the Root Collection Object'),
'#required' => TRUE,
),
),
'islandora_namespace' => array(
'#type' => 'fieldset',
'#title' => t('Namespaces'),
'islandora_namespace_restriction_enforced' => array(
'#type' => 'checkbox',
'#title' => t('Enforce namespace restrictions'),
'#description' => t("Allow administrator to restrict user's access to the PID namepaces listed below"),
'#default_value' => $restrict_namespaces,
),
'islandora_pids_allowed' => array(
'#type' => 'textfield',
'#title' => t('PID namespaces allowed in this Drupal install'),
'#description' => t('A list of PID namespaces, separated by spaces, that users are permitted to access from this Drupal installation. <br /> This could be more than a simple namespace, e.g. <b>demo:mydemos</b>. <br /> The namespace <b>islandora:</b> is reserved, and is always allowed.'),
'#default_value' => variable_get('islandora_pids_allowed', 'default: demo: changeme: ilives: islandora-book: books: newspapers: '),
'#states' => array(
'invisible' => array(
':input[name="islandora_namespace_restriction_enforced"]' => array('checked' => FALSE),
),
),
),
),
),
);
return system_settings_form($form);
}
$form = array();
if (isset($form_state['values']['islandora_base_url'])) {
$url = $form_state['values']['islandora_base_url'];
}
else {
$url = variable_get('islandora_base_url', 'http://localhost:8080/fedora');
}
/**
* Gets a message which describes if the repository is accessible.
*
* Also describes if the user is considered an authenticated user by the
* repository.
*
* @param string $url
* The url to the Fedora Repository.
*
* @return string
* A message describing the accessibility of the repository at the given url.
*/
function islandora_admin_settings_form_repository_access_message($url) {
$info = $dc = FALSE;
$connection = islandora_get_tuque_connection(NULL, $url);
if (!$connection) {
return;
}
try {
$info = $connection->api->a->describeRepository();
}
catch (RepositoryException $e) {
$info = FALSE;
}
if ($info) {
if ($connection) {
try {
$info = $connection->api->a->describeRepository();
// If we are able to successfully call API-M::getDatastream, assume we are
// an authenticated user, as API-M is usally locked down.
$dc = $connection->api->m->getDatastream('fedora-system:ContentModel-3.0', 'DC');
}
catch (RepositoryException $e) {
$dc = FALSE;
// Ignore, we only testing to see what is accessible.
}
}
if ($info) {
if ($dc) {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array()));
$confirmation_message .= t('Successfully connected to Fedora Server (Version !version).', array(
'!version' => $info['repositoryVersion']));
}
else {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-warning.png', 'attributes' => array()));
$confirmation_message .= t('Unable to authenticate when connecting to to Fedora Server (Version !version). Please configure the !filter.',
array('!version' => $info['repositoryVersion'], '!filter' => 'Drupal Filter'));
}
if ($info && $dc) {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array()));
$confirmation_message .= t('Successfully connected to Fedora Server (Version !version).', array(
'!version' => $info['repositoryVersion']));
}
elseif ($info) {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-warning.png', 'attributes' => array()));
$confirmation_message .= t('Unable to authenticate when connecting to to Fedora Server (Version !version). Please configure the !filter.', array(
'!version' => $info['repositoryVersion'], '!filter' => 'Drupal Filter'));
}
else {
$confirmation_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array()));
$confirmation_message .= t('Unable to connect to Fedora server at !islandora_url', array(
'!islandora_url' => $url));
}
$form['islandora_tabs'] = array(
'#type' => 'vertical_tabs',
);
$form['islandora_tabs']['islandora_general'] = array(
'#type' => 'fieldset',
'#title' => t('General Configuarion'),
);
// Ajax wrapper for url checking.
$form['islandora_tabs']['islandora_general']['wrapper'] = array(
'#prefix' => '<div id="islandora-url">',
'#suffix' => '</div>',
'#type' => 'markup',
);
$form['islandora_tabs']['islandora_general']['wrapper']['islandora_base_url'] = array(
'#type' => 'textfield',
'#title' => t('Fedora base URL'),
'#default_value' => variable_get('islandora_base_url', 'http://localhost:8080/fedora'),
'#description' => t('The URL to use for REST connections <br /> !confirmation_message', array(
'!confirmation_message' => $confirmation_message,
)),
'#required' => TRUE,
'#ajax' => array(
'callback' => 'islandora_update_url_div',
'wrapper' => 'islandora-url',
'effect' => 'fade',
'event' => 'blur',
'progress' => array('type' => 'throbber'),
),
);
$form['islandora_tabs']['islandora_general']['islandora_repository_pid'] = array(
'#type' => 'textfield',
'#title' => t('Root Collection PID'),
'#default_value' => variable_get('islandora_repository_pid', 'islandora:root'),
'#description' => t('The PID of the Root Collection Object'),
'#required' => TRUE,
);
$form['islandora_tabs']['islandora_namespace'] = array(
'#type' => 'fieldset',
'#title' => t('Namespaces'),
);
$form['islandora_tabs']['islandora_namespace']['wrapper'] = array(
'#type' => 'markup',
'#prefix' => '<div id="islandora-namespace">',
'#suffix' => '</div>',
);
$form['islandora_tabs']['islandora_namespace']['wrapper']['islandora_namespace_restriction_enforced'] = array(
'#weight' => -1,
'#type' => 'checkbox',
'#title' => t('Enforce namespace restrictions'),
'#description' => t("Allow administrator to restrict user's access to the PID namepaces listed below"),
'#default_value' => variable_get('islandora_namespace_restriction_enforced', FALSE),
'#ajax' => array(
'callback' => 'islandora_update_namespace_div',
'wrapper' => 'islandora-namespace',
'effect' => 'fade',
'event' => 'change',
'progress' => array('type' => 'throbber'),
),
);
if (isset($form_state['values']['islandora_namespace_restriction_enforced'])) {
$namespaces = $form_state['values']['islandora_namespace_restriction_enforced'];
}
else {
$namespaces = variable_get('islandora_namespace_restriction_enforced', FALSE);
}
if ($namespaces) {
$form['islandora_tabs']['islandora_namespace']['wrapper']['islandora_pids_allowed'] = array(
'#type' => 'textfield',
'#title' => t('PID namespaces allowed in this Drupal install'),
'#default_value' => variable_get('islandora_pids_allowed', 'default: demo: changeme: ilives: islandora-book: books: newspapers: '),
'#description' => t('A space separated list of PID namespaces that users are permitted to access from this Drupal installation. <br /> This could be more than a simple namespace ie demo:mydemos. <br /> islandora: is reserved and is always allowed.'),
'#weight' => 0,
);
}
return system_settings_form($form);
return $confirmation_message;
}
/**
@ -168,18 +140,3 @@ function islandora_repository_admin(array $form, array &$form_state) {
function islandora_update_url_div(array $form, array $form_state) {
return $form['islandora_tabs']['islandora_general']['wrapper'];
}
/**
* Get the element to render for the AJAX event that triggered this callback.
*
* @param array $form
* The Drupal form definition.
* @param array $form_state
* The Drupal form state.
*
* @return array
* The form element to render.
*/
function islandora_update_namespace_div(array $form, array $form_state) {
return $form['islandora_tabs']['islandora_namespace']['wrapper'];
}

78
includes/breadcrumb.inc

@ -14,7 +14,7 @@
* ancestry which is identified by any of the following RELS-EXT terms
* (isMemberOf,isMemberOfCollection,isPartOf).
*
* @param FedoraObject $object
* @param AbstractObject $object
* An object whose ancestry will be mapped to bread-crumbs.
*
* @see drupal_set_breadcrumb()
@ -25,13 +25,8 @@
* 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);
$breadcrumbs = islandora_get_breadcrumbs_recursive($object->id, $object->repository);
array_pop($breadcrumbs);
return $breadcrumbs;
}
@ -40,30 +35,44 @@ function islandora_get_breadcrumbs($object) {
*
* @todo Make fully recursive...
*
* @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.
* The object id whose parent will be fetched for the next link.
* @param FedoraRepository $repository
* The fedora repository.
* @param array $context
* An associative array of context for internal use when recursing. Currently
* only used to track a single value:
* - level: The number of child-parent relationships to follow. Defaults to
* 10.
*
* @return array
* An array of links representing the breadcrumb trail, "root" first.
*/
function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRepository $repository) {
function islandora_get_breadcrumbs_recursive($pid, FedoraRepository $repository, array &$context = NULL) {
// Before executing the query, we have a base case of accessing the top-level
// collection.
static $max_level = 10;
static $level = -1;
if (count($breadcrumbs) === 0) {
$level = $max_level;
if ($context === NULL) {
$context['level'] = 10;
}
$root = variable_get('islandora_repository_pid', 'islandora:root');
if ($pid == $root) {
$breadcrumbs[] = l(menu_get_active_title(), 'islandora');
$breadcrumbs[] = l(t('Home'), '<front>');
$title = 'Islandora Repository';
$mlid = db_select('menu_links', 'ml')
->condition('ml.link_path', 'islandora')
->fields('ml', array('mlid'))
->execute()
->fetchField();
if ($mlid) {
$link = menu_link_load($mlid);
$title = (isset($link['title']) ? $link['title'] : $title);
}
return array(
l(t('Home'), '<front>'),
l($title, 'islandora'),
);
}
else {
$query_string = 'select $parentObject $title $content from <#ri>
@ -82,7 +91,7 @@ function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRe
order by $title desc';
$results = $repository->ri->itqlQuery($query_string);
if (count($results) > 0 && $level > 0) {
if (count($results) > 0 && $context['level'] > 0) {
$parent = $results[0]['parentObject']['value'];
$this_title = $results[0]['title']['value'];
@ -90,16 +99,23 @@ function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRe
$this_title = t('-');
}
$breadcrumbs[] = l($this_title, "islandora/object/$pid");
$level--;
islandora_get_breadcrumbs_recursive($parent, $breadcrumbs, $repository);
$context['level']--;
return array_merge(
islandora_get_breadcrumbs_recursive($parent, $repository, $context),
array(
l($this_title, "islandora/object/$pid"),
)
);
}
else {
// 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);
// Add an non-link, as we don't know how to get back to the root, and
// render the last two links and break (on the next pass).
return array_merge(
islandora_get_breadcrumbs_recursive($root, $repository, $context),
array(
'...',
)
);
}
}
}

57
includes/content_model.autocomplete.inc

@ -0,0 +1,57 @@
<?php
/**
* @file
* Autocomplete functionality for content models in Islandora.
*/
/**
* Autocomplete the content model name.
*
* @param string $string
* A search string.
*
* @return string
* The rendered JSON results.
*/
function islandora_content_model_autocomplete($string) {
$content_models = islandora_get_content_model_names();
$output = array();
foreach ($content_models as $model => $label) {
if (preg_match("/{$string}/i", $label) !== 0) {
$output[$model] = $label;
}
}
return drupal_json_output($output);
}
/**
* Gets a map of form names suitable for use as select #options.
*/
function islandora_get_content_model_names() {
module_load_include('inc', 'islandora', 'includes/utilities');
$results = islandora_get_content_models();
$ret = array();
foreach ($results as $result) {
$ret[$result['pid']] = "{$result['label']} ({$result['pid']})";
}
return $ret;
}
/**
* Minor array transformation.
*
* @param array $content
* The array of results as returned from Tuque's RI query interface.
*
* @return array
* An array of results in a more usable format.
*/
function islandora_parse_query($content) {
$content_models = array();
foreach ($content as $model) {
$content_models[] = $model['object']['value'];
}
$content_models = array_unique($content_models);
$content_models = array_values($content_models);
return $content_models;
}

84
includes/datastream.inc

@ -8,10 +8,10 @@
/**
* Callback to download the given datastream to the users computer.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to download.
*/
function islandora_download_datastream(FedoraDatastream $datastream) {
function islandora_download_datastream(AbstractDatastream $datastream) {
islandora_view_datastream($datastream, TRUE);
}
@ -21,13 +21,13 @@ function islandora_download_datastream(FedoraDatastream $datastream) {
* @note
* This function calls exit().
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to view/download.
* @param bool $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(FedoraDatastream $datastream, $download = FALSE) {
function islandora_view_datastream(AbstractDatastream $datastream, $download = FALSE) {
header_remove('Cache-Control');
header_remove('Expires');
header('Content-type: ' . $datastream->mimetype);
@ -51,14 +51,14 @@ function islandora_view_datastream(FedoraDatastream $datastream, $download = FAL
/**
* Get the human readable size of the given datastream.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to check.
*
* @return string
* A human readable size of the given datastream, or '-' if the size could not
* be determined.
*/
function islandora_datastream_get_human_readable_size(FedoraDatastream $datastream) {
function islandora_datastream_get_human_readable_size(AbstractDatastream $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) : '-';
@ -67,47 +67,53 @@ function islandora_datastream_get_human_readable_size(FedoraDatastream $datastre
/**
* Get either the 'view' or 'download' url for the given datastream if possible.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to generated the url to.
*
* @return string
* either the 'view' or 'download' url for the given datastream.
*/
function islandora_datastream_get_url(FedoraDatastream $datastream, $type = 'download') {
function islandora_datastream_get_url(AbstractDatastream $datastream, $type = 'download') {
return $datastream->controlGroup == 'R' ? $datastream->url : "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/$type";
}
/**
* Gets the delete link.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to generated the url to.
*/
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") : '';
function islandora_datastream_get_delete_link(AbstractDatastream $datastream) {
$message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_delete_link" theme implementation.');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
return theme('islandora_datastream_delete_link', array(
'datastream' => $datastream,
));
}
/**
* Gets the edit link.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to generated the url to.
*/
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") : '';
function islandora_datastream_edit_get_link(AbstractDatastream $datastream) {
$message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_edit_link" theme implementation.');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
return theme('islandora_datastream_edit_link', array(
'datastream' => $datastream,
));
}
/**
* Display the edit datastream page.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to edit.
*/
function islandora_edit_datastream(FedoraDatastream $datastream) {
function islandora_edit_datastream(AbstractDatastream $datastream) {
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $datastream->parent, $datastream);
$edit_count = count($edit_registry);
switch ($edit_count) {
@ -144,3 +150,41 @@ function islandora_edit_datastream_registry_render(array $edit_registry) {
'#markup' => $markup,
);
}
/**
* Get markup for a download link.
*
* @param AbstractDatastream $datastream
* The datastream for which to generate a link.
*
* @return string
* Either the link markup if the user has access or an empty string if the
* user is not allowed to see the given datastream.
*/
function islandora_datastream_get_download_link(AbstractDatastream $datastream) {
$message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_download_link" theme implementation.');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
return theme('islandora_datastream_download_link', array(
'datastream' => $datastream,
));
}
/**
* Get markup for a view link.
*
* @param AbstractDatastream $datastream
* The datastream for which to generate a link.
*
* @return string
* Either the link markup if the user has access or a string containing the
* datastream ID if the user is not allowed to see the given datastream.
*/
function islandora_datastream_get_view_link(AbstractDatastream $datastream) {
$message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_view_link" theme implementation.');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
return theme('islandora_datastream_view_link', array(
'datastream' => $datastream,
));
}

6
includes/delete_datastream.form.inc

@ -12,13 +12,13 @@
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to be deleted.
*
* @return array
* The drupal form definition.
*/
function islandora_delete_datastream_form(array $form, array &$form_state, FedoraDatastream $datastream) {
function islandora_delete_datastream_form(array $form, array &$form_state, AbstractDatastream $datastream) {
$form_state['datastream'] = $datastream;
return confirm_form($form,
t('Are you sure you want to delete the %dsid datastream?', array('%dsid' => $datastream->id)),
@ -32,7 +32,7 @@ function islandora_delete_datastream_form(array $form, array &$form_state, Fedor
/**
* Submit handler for the delete datastream form.
*
* Purges/Delete's the given FedoraDatastream if possible.
* Purges/Delete's the given AbstractDatastream if possible.
*
* The ISLANDORA_PRE_PURGE_DATASTREAM_HOOK will query other modules as to
* whether the given FedoraDatastream

4
includes/delete_object.form.inc

@ -12,13 +12,13 @@
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraObject $object
* @param AbstractObject $object
* The object to be deleted.
*
* @return array
* The drupal form definition.
*/
function islandora_delete_object_form(array $form, array &$form_state, FedoraObject $object) {
function islandora_delete_object_form(array $form, array &$form_state, AbstractObject $object) {
$form_state['object'] = $object;
return confirm_form($form,
t('Are you sure you want to delete %title?', array('%title' => $object->label)),

485
includes/ingest.form.inc

@ -5,6 +5,25 @@
* Defines the multi-page ingest form and any relevant hooks and functions.
*/
/**
* Checks if the given configuration can be used to display the ingest form.
*
* @param array $configuration
* The list of key/value pairs of configuration.
*
* @return bool
* TRUE if the give configuration defines one or more form steps, FALSE
* otherwise.
*/
function islandora_ingest_can_display_ingest_form(array $configuration) {
$form_state = array();
islandora_ingest_form_init_form_state_storage($form_state, $configuration);
$form_steps = islandora_ingest_form_get_form_steps($form_state);
// Forget the stubbed steps for the remainder of this request.
drupal_static_reset('islandora_ingest_form_get_steps');
return count($form_steps) > 0;
}
/**
* Ingest form build function.
*
@ -26,6 +45,8 @@
* be related.
* - models: An array of content model PIDs, to which the new object might
* subscribe
* - parent: The parent of the child to be ingested. This is needed for XACML
* to correctly apply the parent's POLICY to children.
*
* @return array
* The form definition of the current step.
@ -35,33 +56,13 @@ function islandora_ingest_form(array $form, array &$form_state, array $configura
islandora_ingest_form_init_form_state_storage($form_state, $configuration);
return islandora_ingest_form_execute_step($form, $form_state);
}
catch(Exception $e) {
catch (Exception $e) {
drupal_set_message($e->getMessage(), 'error');
return array(array(
'#markup' => l(t('Back'), 'javascript:window.history.back();', array('external' => TRUE))));
}
}
/**
* Validates the given ingest configuration.
*
* At the moment it only requires that models are present.
*
* @todo Add hook for manipulating/validating the configuration.
*
* @see islandora_ingest_form()
*
* @throws InvalidArgumentException
*
* @param array $configuration
* The key value pairs that are used to build the multi-paged ingest process.
*/
function islandora_ingest_form_validate_configuration(array $configuration) {
if (empty($configuration['models'])) {
throw new InvalidArgumentException('Ingest configuration not vaild, no models were given');
}
}
/**
* Initializes the form_state storage for use in the ingest multi-page forms.
*
@ -73,18 +74,62 @@ function islandora_ingest_form_validate_configuration(array $configuration) {
*/
function islandora_ingest_form_init_form_state_storage(array &$form_state, array $configuration) {
if (empty($form_state['islandora'])) {
// Validate the configuration before we use it.
islandora_ingest_form_validate_configuration($configuration);
$object = islandora_ingest_form_prepare_new_object($configuration);
$objects = isset($configuration['objects']) ? $configuration['objects'] : array();
if (empty($objects)) {
$objects[] = islandora_ingest_form_prepare_new_object($configuration);
}
$configuration['models'] = isset($configuration['models']) ? $configuration['models'] : array();
// Make sure the models actually exist.
foreach ($configuration['models'] as $key => $model) {
if (!islandora_object_load($model)) {
unset($configuration['models'][$key]);
}
}
// No need to persist the 'objects' within the configuration.
unset($configuration['objects']);
// Required for step hooks.
$form_state['islandora'] = array(
'step_id' => NULL,
'objects' => array($object),
'objects' => $objects,
'shared_storage' => $configuration,
'step_storage' => array(),
);
// Must be called after $form_state['islandora'] is initialized, otherwise,
// the values in 'islandora' would not be availible to the step hooks.
$form_state['islandora']['step_id'] = islandora_ingest_form_get_first_step_id($form_state);
}
}
/**
* Get the first step ID.
*
* @param array $form_state
* The Drupal form state.
*
* @return string
* The 'id' of the very first step.
*/
function islandora_ingest_form_get_first_step_id(array &$form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
$keys = array_keys($steps);
return array_shift($keys);
}
/**
* Get the last step ID.
*
* @param array $form_state
* The Drupal form state.
*
* @return string
* The 'id' of the very last step.
*/
function islandora_ingest_form_get_last_step_id(array &$form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
$keys = array_keys($steps);
return array_pop($keys);
}
/**
* Prepares a new object based on the given configuration.
*
@ -96,27 +141,31 @@ function islandora_ingest_form_init_form_state_storage(array &$form_state, array
*/
function islandora_ingest_form_prepare_new_object(array $configuration) {
module_load_include('inc', 'islandora', 'includes/utilities');
// ID is more specific than namespace so it will take precedence.
$id = isset($configuration['namespace']) ? $configuration['namespace'] : 'islandora';
$id = isset($configuration['id']) ? $configuration['id'] : $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']);
return islandora_prepare_new_object($id, $label, array(), array(), $relationships);
if (empty($configuration['object'])) {
$message = islandora_deprecated('7.x-1.2', t('Please use "objects" as the default ingest form configuration property.'));
trigger_error(filter_xss($message), E_USER_DEPRECATED);
// ID is more specific than namespace so it will take precedence.
$id = isset($configuration['namespace']) ? $configuration['namespace'] : 'islandora';
$id = isset($configuration['id']) ? $configuration['id'] : $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']);
return islandora_prepare_new_object($id, $label, array(), array(), $relationships);
}
return $configuration['object'];
}
/**
* Gets the given/current step.
*
* The current step is returned if no step ID is given. If the current step is
* not defined it's assume to be the first step.
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step_id
* The ID of the step.
* The ID of the step. The current step is returned if no step ID is given.
*
* @return array
* The given/current step if found, NULL otherwise.
@ -130,10 +179,48 @@ function islandora_ingest_form_get_step(array &$form_state, $step_id = NULL) {
return NULL;
}
/**
* Gets the next step.
*
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step
* The step relative to the result, if not provided the current step is used.
*
* @return string
* The next step if found, NULL otherwise.
*/
function islandora_ingest_form_get_next_step(array &$form_state, array $step = NULL) {
$step = isset($step) ? $step : islandora_ingest_form_get_step($form_state);
$next_step_id = islandora_ingest_form_get_next_step_id($form_state, $step['id']);
return isset($next_step_id) ? islandora_ingest_form_get_step($form_state, $next_step_id) : NULL;
}
/**
* Gets the previous step.
*
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step
* The step relative to the result, if not provided the current step is used.
*
* @return string
* The next step if found, NULL otherwise.
*/
function islandora_ingest_form_get_previous_step(array &$form_state, array $step = NULL) {
$step = isset($step) ? $step : islandora_ingest_form_get_step($form_state);
$previous_step_id = islandora_ingest_form_get_previous_step_id($form_state, $step['id']);
return isset($previous_step_id) ? islandora_ingest_form_get_step($form_state, $previous_step_id) : NULL;
}
/**
* Gets the ID of the current step.
*
* If a current step is not defined, its assumed to be the first step.
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
@ -142,26 +229,25 @@ function islandora_ingest_form_get_step(array &$form_state, $step_id = NULL) {
* The step ID.
*/
function islandora_ingest_form_get_current_step_id(array &$form_state) {
if (empty($form_state['islandora']['step_id'])) {
$steps = islandora_ingest_form_get_steps($form_state);
return array_shift(array_keys($steps));
}
return $form_state['islandora']['step_id'];
}
/**
* Gets the ID of the next step.
*
* If a current step is not defined, its assumed to be the first step.
* If the current step is not defined it's assumed that all steps have executed.
*
* @param array $form_state
* The Drupal form state.
* @param string $step_id
* The ID of the step relative to the result, if not provided the current
* step_id is used.
*
* @return string
* The next step ID if found, NULL otherwise.
*/
function islandora_ingest_form_get_next_step_id(array &$form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
function islandora_ingest_form_get_next_step_id(array &$form_state, $step_id = NULL) {
$step_id = isset($step_id) ? $step_id : islandora_ingest_form_get_current_step_id($form_state);
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
$index = array_search($step_id, $step_ids);
$count = count($step_ids);
@ -174,16 +260,25 @@ function islandora_ingest_form_get_next_step_id(array &$form_state) {
/**
* Gets the ID of the previous step.
*
* If a current step is not defined, its assumed to be the first step.
* If the current step is not defined it's assumed that all steps have executed.
* In such cases the last step will be returned.
*
* @param array $form_state
* The Drupal form state.
* @param string $step_id
* The ID of the step relative to the result, if not provided the current
* step_id is used.
*
* @return string
* The previous step ID if found, NULL otherwise.
*/
function islandora_ingest_form_get_previous_step_id(array &$form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
function islandora_ingest_form_get_previous_step_id(array &$form_state, $step_id = NULL) {
$step_id = isset($step_id) ? $step_id : islandora_ingest_form_get_current_step_id($form_state);
// If the current step is not defined it's assumed that all steps have
// executed. So return the very last step.
if ($step_id == NULL) {
return islandora_ingest_form_get_last_step_id($form_state);
}
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
$index = array_search($step_id, $step_ids);
if ($index !== FALSE && --$index >= 0) {
@ -203,11 +298,9 @@ function islandora_ingest_form_increment_step(array &$form_state) {
// of the current step could have added/removed a step.
drupal_static_reset('islandora_ingest_form_get_steps');
$next_step_id = islandora_ingest_form_get_next_step_id($form_state);
if (isset($next_step_id)) {
islandora_ingest_form_stash_info($form_state);
$form_state['islandora']['step_id'] = $next_step_id;
islandora_ingest_form_grab_info($form_state);
}
islandora_ingest_form_stash_info($form_state);
$form_state['islandora']['step_id'] = $next_step_id;
islandora_ingest_form_grab_info($form_state);
}
/**
@ -218,6 +311,7 @@ function islandora_ingest_form_increment_step(array &$form_state) {
*/
function islandora_ingest_form_decrement_step(array &$form_state) {
$previous_step_id = islandora_ingest_form_get_previous_step_id($form_state);
// Don't decrement passed the first step.
if (isset($previous_step_id)) {
islandora_ingest_form_stash_info($form_state);
$form_state['islandora']['step_id'] = $previous_step_id;
@ -225,33 +319,6 @@ function islandora_ingest_form_decrement_step(array &$form_state) {
}
}
/**
* Build a list of steps given only configuration.
*
* XXX: This is used to give an indication of whether there are any steps for a
* given list of content models.
*
* @param array $configuration
* The list of key/value pairs of configuration.
*/
function islandora_ingest_get_approximate_steps(array $configuration) {
try {
islandora_ingest_form_validate_configuration($configuration);
}
catch(InvalidArgumentException $e) {
// Don't log or display exception.
return array();
}
$stubbed_form_state = array(
'islandora' => array(
'shared_storage' => $configuration,
),
);
$steps = islandora_ingest_form_get_steps($stubbed_form_state);
drupal_static_reset('islandora_ingest_form_get_steps');
return $steps;
}
/**
* Executes the current step.
*
@ -266,16 +333,19 @@ function islandora_ingest_get_approximate_steps(array $configuration) {
* @return array
* The form definition of the current step.
*/
function islandora_ingest_form_execute_step(array $form, array &$form_state) {
function islandora_ingest_form_execute_step(array $form, array &$form_state, $step_id = NULL) {
// Load any required files for the current step.
islandora_ingest_form_load_include($form_state);
$step = islandora_ingest_form_get_step($form_state);
$step = isset($step_id) ? islandora_ingest_form_get_step($form_state) : islandora_ingest_form_get_step($form_state, $step_id);
switch ($step['type']) {
case 'callback':
// Execute all the consecutive callbacks, and move then attempt to process
// the next step.
islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
return islandora_ingest_form_execute_step($form, $form_state);
case 'form':
$args = array($form, &$form_state);
$args = isset($step['args']) ? array_merge($args, $step['args']) : $args;
$form = call_user_func_array($step['form_id'], $args);
return islandora_ingest_form_stepify($form, $form_state, $step);
return islandora_ingest_form_execute_form_step($form, $form_state, $step);
case 'batch':
// @todo Implement if possible.
@ -284,6 +354,102 @@ function islandora_ingest_form_execute_step(array $form, array &$form_state) {
return array();
}
/**
* Execute the given 'form' step.
*
* Assumes the given step is a 'form' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*
* @return array
* The form definition of the given step.
*/
function islandora_ingest_form_execute_form_step(array $form, array &$form_state, array $step) {
$args = array($form, &$form_state);
$args = isset($step['args']) ? array_merge($args, $step['args']) : $args;
$shared_storage = islandora_ingest_form_get_shared_storage($form_state);
// Build the form step.
$form = call_user_func_array($step['form_id'], $args);
// Since the list of steps depends on the shared storage we will rebuild the
// list of steps if the shared storage has changed. This must be done before
// stepifying, so the prev/next buttons get updated.
if ($shared_storage != islandora_ingest_form_get_shared_storage($form_state)) {
drupal_static_reset('islandora_ingest_form_get_steps');
}
return islandora_ingest_form_stepify($form, $form_state, $step);
}
/**
* Execute the given 'callback' step and any consecutive 'callback' steps.
*
* Assumes the given step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_execute_consecutive_callback_steps(array $form, array &$form_state, array $step) {
do {
islandora_ingest_form_execute_callback_step($form, $form_state, $step);
islandora_ingest_form_increment_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
} while (isset($step) && $step['type'] == 'callback');
}
/**
* Execute the given 'callback' step.
*
* Assumes the given step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_execute_callback_step(array $form, array &$form_state, array $step) {
$args = array(&$form_state);
$args = isset($step['do_function']['args']) ? array_merge($args, $step['do_function']['args']) : $args;
call_user_func_array($step['do_function']['function'], $args);
}
/**
* Undo the given 'callback' step and any consecutive 'callback' steps.
*
* Assumes the given $step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_undo_consecutive_callback_steps(array $form, array &$form_state, array $step) {
do {
islandora_ingest_form_undo_callback_step($form, $form_state, $step);
islandora_ingest_form_decrement_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
} while (isset($step) && $step['type'] == 'callback');
}
/**
* Undo the given 'callback' step.
*
* Assumes the given $step is a 'callback' step.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_form_undo_callback_step(array $form, array &$form_state, array $step) {
$args = array(&$form_state);
$args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args;
call_user_func_array($step['undo_function']['function'], $args);
}
/**
* Append Prev/Next buttons submit/validation handlers etc.
*
@ -293,18 +459,24 @@ function islandora_ingest_form_execute_step(array $form, array &$form_state) {
* The Drupal form state.
*
* @return array
* The stepified drupal form definition for the given step.
* The stepified Drupal form definition for the given step.
*/
function islandora_ingest_form_stepify(array $form, array &$form_state) {
$first_step = islandora_ingest_form_on_first_step($form_state);
$last_step = islandora_ingest_form_on_last_step($form_state);
$form['prev'] = $first_step ? NULL : islandora_ingest_form_previous_button($form_state);
$form['next'] = $last_step ? islandora_ingest_form_ingest_button($form_state) : islandora_ingest_form_next_button($form_state);
function islandora_ingest_form_stepify(array $form, array &$form_state, $step) {
$first_form_step = islandora_ingest_form_on_first_form_step($form_state);
$last_form_step = islandora_ingest_form_on_last_form_step($form_state);
$form['form_step_id'] = array(
'#type' => 'hidden',
'#value' => islandora_ingest_form_get_current_step_id($form_state),
);
$form['prev'] = $first_form_step ? NULL : islandora_ingest_form_previous_button($form_state);
$form['next'] = $last_form_step ? islandora_ingest_form_ingest_button($form_state) : islandora_ingest_form_next_button($form_state);
// Allow for a hook_form_FORM_ID_alter().
drupal_alter(array('form_' . $step['form_id'], 'form'), $form, $form_state, $step['form_id']);
return $form;
}
/**
* Checks if we are on the first step.
* Checks if we are on the first form step.
*
* @param array $form_state
* The Drupal form state.
@ -312,14 +484,12 @@ function islandora_ingest_form_stepify(array $form, array &$form_state) {
* @return bool
* TRUE if we are currently on the first step, FALSE otherwise.
*/
function islandora_ingest_form_on_first_step(array &$form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
return array_search($step_id, $step_ids) == 0;
function islandora_ingest_form_on_first_form_step(array &$form_state) {
return !islandora_ingest_form_get_previous_form_step($form_state);
}
/**
* Checks if we are on the last step.
* Checks if we are on the last form step.
*
* @param array $form_state
* The Drupal form state.
@ -327,11 +497,42 @@ function islandora_ingest_form_on_first_step(array &$form_state) {
* @return bool
* TRUE if we are currently on the last step, FALSE otherwise.
*/
function islandora_ingest_form_on_last_step(array &$form_state) {
$step_id = islandora_ingest_form_get_current_step_id($form_state);
$step_ids = array_keys(islandora_ingest_form_get_steps($form_state));
$count = count($step_ids);
return array_search($step_id, $step_ids) == --$count;
function islandora_ingest_form_on_last_form_step(array &$form_state) {
return !islandora_ingest_form_get_next_form_step($form_state);
}
/**
* Get the previous form step relative to the current step.
*
* @param array $form_state
* The Drupal form state.
*
* @return array
* The previous form step if one exists, NULL otherwise.
*/
function islandora_ingest_form_get_previous_form_step(array &$form_state) {
$step = NULL;
do {
$step = islandora_ingest_form_get_previous_step($form_state, $step);
} while (isset($step) && $step['type'] != 'form');
return $step;
}
/**
* Get the next form step relative to the current step.
*
* @param array $form_state
* The Drupal form state.
*
* @return array
* The next form step if one exists, NULL otherwise.
*/
function islandora_ingest_form_get_next_form_step(array &$form_state) {
$step = NULL;
do {
$step = islandora_ingest_form_get_next_step($form_state, $step);
} while (isset($step) && $step['type'] != 'form');
return $step;
}
/**
@ -346,13 +547,12 @@ function islandora_ingest_form_on_last_step(array &$form_state) {
* The previous button for the ingest form.
*/
function islandora_ingest_form_previous_button(array &$form_state) {
// Before we move back to the previous step we should tell the previous step
// Before we move back to the previous step we should tell the previous steps
// to undo whatever its submit handler did.
$prev_step_id = islandora_ingest_form_get_previous_step_id($form_state);
$prev_step = islandora_ingest_form_get_step($form_state, $prev_step_id);
$form_id = $prev_step['form_id'];
$prev_form_step = islandora_ingest_form_get_previous_form_step($form_state);
$form_id = $prev_form_step['form_id'];
$submit_callback = $form_id . '_undo_submit';
$submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_previous_submit') : array('islandora_ingest_form_undo_submit');
$submit = function_exists($submit_callback) ? array('islandora_ingest_form_previous_submit', $submit_callback) : array('islandora_ingest_form_previous_submit');
return array(
'#type' => 'submit',
'#value' => t('Previous'),
@ -383,6 +583,11 @@ function islandora_ingest_form_previous_button(array &$form_state) {
*/
function islandora_ingest_form_previous_submit(array $form, array &$form_state) {
islandora_ingest_form_decrement_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
// Undo all callbacks that occured after the previous step.
if ($step['type'] == 'callback') {
islandora_ingest_form_undo_consecutive_callback_steps($form, $form_state, $step);
}
$form_state['rebuild'] = TRUE;
}
@ -438,8 +643,10 @@ function islandora_ingest_form_next_submit(array $form, array &$form_state) {
*/
function islandora_ingest_form_stash_info(array &$form_state) {
$storage = &islandora_ingest_form_get_step_storage($form_state);
$storage['values'] = $form_state['values'];
unset($form_state['values']);
if ($storage && isset($form_state['values'])) {
$storage['values'] = $form_state['values'];
unset($form_state['values']);
}
}
/**
@ -485,12 +692,17 @@ function islandora_ingest_form_ingest_button(array &$form_state) {
*
* 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) {
// Execute any remaining callbacks.
islandora_ingest_form_increment_step($form_state);
$step = islandora_ingest_form_get_step($form_state);
if (isset($step) && $step['type'] == 'callback') {
islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
}
// Ingest the objects.
foreach ($form_state['islandora']['objects'] as $object) {
try {
islandora_add_object($object);
@ -499,7 +711,7 @@ function islandora_ingest_form_submit(array $form, array &$form_state) {
catch (Exception $e) {
// If post hooks throws it may already exist at this point but may be
// invalid, so don't say failed.
watchdog('islandora', $e->getMessage(), NULL, WATCHDOG_ERROR);
watchdog('islandora', 'Exception Message: @exception.', array('@exception' => $e->getMessage()), 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');
}
}
@ -537,7 +749,7 @@ function &islandora_ingest_form_get_objects(array &$form_state) {
*/
function islandora_ingest_form_get_object(array &$form_state) {
$objects = &islandora_ingest_form_get_objects($form_state);
return current($objects);
return reset($objects);
}
/**
@ -559,7 +771,8 @@ function &islandora_ingest_form_get_step_storage(array &$form_state, $step_id =
}
return $form_state['islandora']['step_storage'][$step_id];
}
return NULL;
$undefined_step_storage = array();
return $undefined_step_storage;
}
/**
@ -617,6 +830,8 @@ function islandora_ingest_form_get_steps(array &$form_state) {
$shared_storage = &islandora_ingest_form_get_shared_storage($form_state);
foreach (islandora_build_hook_list(ISLANDORA_INGEST_STEP_HOOK, $shared_storage['models']) as $hook) {
// Required for pass by reference.
// @todo Change this around so that it isn't passed by reference, there
// Is an alter below that can handle that requirement.
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
$module_steps = (array) $function($form_state);
@ -627,6 +842,46 @@ function islandora_ingest_form_get_steps(array &$form_state) {
foreach (islandora_build_hook_list(ISLANDORA_INGEST_STEP_HOOK, $shared_storage['models']) as $hook) {
drupal_alter($hook, $steps, $form_state);
}
// Add any defaults.
foreach ($steps as $key => &$step) {
$step['id'] = $key;
}
uasort($steps, 'drupal_sort_weight');
return $steps;
}
/**
* Filter the ingest steps to only steps of type 'form'.
*
* @param array $form_state
* The Drupal form state.
*
* @return array
* The list of sorted ingest form steps as defined by all implementers
* of ISLANDORA_INGEST_STEP_HOOK.
*/
function islandora_ingest_form_get_form_steps(array &$form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
$form_step_filter = function($o) {
return $o['type'] == 'form';
};
return array_filter($steps, $form_step_filter);
}
/**
* Filter the ingest steps to only steps of type 'form'.
*
* @param array $form_state
* The Drupal form state.
*
* @return array
* The list of sorted ingest callback steps as defined by all implementers
* of ISLANDORA_INGEST_STEP_HOOK.
*/
function islandora_ingest_form_get_callback_steps(array &$form_state) {
$steps = islandora_ingest_form_get_steps($form_state);
$callback_step_filter = function($o) {
return $o['type'] == 'callback';
};
return array_filter($steps, $callback_step_filter);
}

49
includes/ingest.menu.inc

@ -1,49 +0,0 @@
<?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() {
module_load_include('inc', 'islandora', 'includes/ingest.form');
try {
$configuration = islandora_ingest_get_configuration();
return drupal_get_form('islandora_ingest_form', $configuration);
}
catch(Exception $e) {
$redirect = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '<front>';
// Redirect back to referer or top level collection.
drupal_goto($redirect);
}
}
/**
* Fetches 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]);
}
return $configuration;
}

18
includes/mime_detect.inc

@ -148,7 +148,7 @@ class MimeDetect {
"jp2" => "image/jp2",
"png" => "image/png",
"tiff" => "image/tiff",
"tif" => "image/tif",
"tif" => "image/tiff",
"djvu" => "image/vnd.djvu",
"djv" => "image/vnd.djvu",
"wbmp" => "image/vnd.wap.wbmp",
@ -194,6 +194,11 @@ class MimeDetect {
'bin' => 'application/octet-stream',
);
protected $protectedFileExtensions;
protected $extensionExceptions = array(
// XXX: Deprecated... Only here due to old 'tif' => 'image/tif' mapping...
// The correct MIMEtype is 'image/tiff'.
'image/tif' => 'tif',
);
protected $systemTypes;
protected $systemExts;
protected $etcMimeTypes = '/etc/mime.types';
@ -205,6 +210,7 @@ class MimeDetect {
// Populate the reverse shortlist:
$this->protectedFileExtensions = array_flip($this->protectedMimeTypes);
$this->protectedFileExtensions += $this->extensionExceptions;
// Pick up a local mime.types file if it is available.
if (is_readable('mime.types')) {
@ -366,4 +372,14 @@ class MimeDetect {
return $out;
}
/**
* Gets MIME type array.
*
* @return array
* Returns associative array with exts and mimetypes.
*/
public function getMimeTypes() {
return $this->protectedMimeTypes;
}
}

11
includes/object_properties.form.inc

@ -12,13 +12,13 @@
* The Drupal form.
* @param array $form_state
* The Drupal form state.
* @param FedoraObject $object
* @param AbstractObject $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) {
function islandora_object_properties_form(array $form, array &$form_state, AbstractObject $object) {
drupal_set_title($object->label);
$form_state['object'] = $object;
return array(
@ -30,7 +30,7 @@ function islandora_object_properties_form(array $form, array &$form_state, Fedor
'#title' => t('Item Label'),
'#default_value' => $object->label,
'#required' => 'TRUE',
'#description' => t('A Human readable label'),
'#description' => t('A human-readable label'),
// Double the normal length.
'#size' => 120,
// Max length for a Fedora Label.
@ -43,14 +43,14 @@ function islandora_object_properties_form(array $form, array &$form_state, Fedor
'#title' => t('Owner'),
'#default_value' => $object->owner,
'#required' => FALSE,
'#description' => t('The owner id'),
'#description' => t("The owner's account name"),
'#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'),
'#description' => t("The object's state (active, inactive or deleted)"),
'#type' => 'select',
'#options' => array('A' => 'Active', 'I' => 'Inactive', 'D' => 'Deleted'),
),
@ -60,6 +60,7 @@ function islandora_object_properties_form(array $form, array &$form_state, Fedor
),
'delete' => array(
'#type' => 'submit',
'#access' => islandora_object_access(FEDORA_PURGE, $object),
'#value' => t('Delete'),
'#submit' => array('islandora_object_properties_form_delete'),
'#limit_validation_errors' => array(array('pid')),

125
includes/solution_packs.inc

@ -180,37 +180,55 @@ function islandora_solution_pack_form_submit(array $form, array &$form_state) {
/**
* Batch operation to ingest/reingest required object(s).
*
* @param NewFedoraObject $object
* @param AbstractObject $object
* The object to ingest/reingest.
* @param array $context
* The context of this batch operation.
*/
function islandora_solution_pack_batch_operation_reingest_object(NewFedoraObject $object, array &$context) {
function islandora_solution_pack_batch_operation_reingest_object(AbstractObject $object, array &$context) {
$existing_object = islandora_object_load($object->id);
$deleted = FALSE;
if ($existing_object) {
$deleted = islandora_delete_object($existing_object);
if (!$deleted) {
$object_link = l($existing_object->label, "islandora/object/{$existing_object->id}");
drupal_set_message(t('Failed to purge existing object !object_link.', array(
drupal_set_message(filter_xss(t('Failed to purge existing object !object_link.', array(
'!object_link' => $object_link,
)), 'error');
))), 'error');
// Failed to purge don't attempt to ingest.
return;
}
}
// Object was deleted or did not exist.
$pid = $object->id;
$label = $object->label;
$action = $deleted ? 'reinstalled' : 'installed';
$object_link = l($label, "islandora/object/{$pid}");
$object = islandora_add_object($object);
$msg = $object ? "Successfully $action !object_link." : "Failed to $action @label identified by @pid.";
$params = array(
'@pid' => $pid,
'@label' => $label,
'!object_link' => $object_link,
);
$msg = '';
if ($object) {
if ($deleted) {
$msg = t('Successfully reinstalled !object_link.', $params);
}
else {
$msg = t('Successfully installed !object_link.', $params);
}
}
elseif ($deleted) {
$msg = t('Failed to reinstall @label, identified by @pid.', $params);
}
else {
$msg = t('Failed to install @label, identified by @pid.', $params);
}
$status = $object ? 'status' : 'error';
drupal_set_message(t($msg, array(
'@pid' => $pid,
'@label' => $label,
'!object_link' => $object_link,
)), $status);
drupal_set_message(filter_xss($msg), $status);
}
/**
@ -237,33 +255,37 @@ function islandora_install_solution_pack($module, $op = 'install') {
islandora_uninstall_solution_pack($module);
return;
}
$t = get_t();
// Some general replacements.
$admin_link = l($t('Solution Pack admin'), 'admin/islandora/solution_packs');
$config_link = l($t('Islandora configuration'), 'admin/islandora/configure');
$t_params = array(
'@module' => $module,
'!config_link' => $config_link,
'!admin_link' => $admin_link,
);
module_load_include('module', 'islandora', 'islandora');
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('module', $module, $module);
$info_file = drupal_get_path('module', $module) . "/{$module}.info";
$info_array = drupal_parse_info_file($info_file);
$module_name = $info_array['name'];
$admin_link = l(t('Solution Pack admin'), 'admin/islandora/solution_packs');
$config_link = l(t('Islandora configuration'), 'admin/islandora/configure');
if (!islandora_describe_repository()) {
$msg = '@module: Did not install any objects. Could not connect to the ';
$msg .= 'repository. Please check the settings on the !config_link page ';
$msg .= 'and install the required objects manually on the !admin_link page.';
drupal_set_message(st($msg, array(
'@module' => $module_name,
'!config_link' => $config_link,
'@admin_link' => $admin_link,
)), 'error');
$msg = $t('@module: Did not install any objects. Could not connect to the repository. Please check the settings on the !config_link page and install the required objects manually on the !admin_link page.', $t_params);
drupal_set_message(filter_xss($msg), 'error');
return;
}
$connection = islandora_get_tuque_connection();
$required_objects = module_invoke($module, 'islandora_required_objects', $connection);
$objects = $required_objects[$module]['objects'];
$status_messages = array(
'up_to_date' => 'The object already exists and is up-to-date',
'missing_datastream' => 'The object already exists but is missing a datastream. Please reinstall the object on the !admin_link page',
'out_of_date' => 'The object already exists but is out-of-date. Please update the object on the !admin_link page',
'modified_datastream' => 'The object already exists but datastreams are modified. Please reinstall the object on the !admin_link page',
'up_to_date' => $t('The object already exists and is up-to-date.', $t_params),
'missing_datastream' => $t('The object already exists but is missing a datastream. Please reinstall the object on the !admin_link page.', $t_params),
'out_of_date' => $t('The object already exists but is out-of-date. Please update the object on the !admin_link page.', $t_params),
'modified_datastream' => $t('The object already exists but datastreams are modified. Please reinstall the object on the !admin_link page.', $t_params),
);
foreach ($objects as $object) {
$query = $connection->api->a->findObjects('query', 'pid=' . $object->id);
@ -272,26 +294,25 @@ function islandora_install_solution_pack($module, $op = 'install') {
$object_link = l($label, "islandora/object/{$object->id}");
if ($already_exists) {
$object_status = islandora_check_object_status($object);
$status_msg = $status_messages[$object_status['status']];
drupal_set_message(st("@module: Did not install !object_link. $status_msg.", array(
'@module' => $module_name,
$here_params = array(
'!summary' => $t("@module: Did not install !object_link.", array(
'!object_link' => $object_link,
'!admin_link' => $admin_link,
)), 'warning');
) + $t_params),
'!description' => $status_messages[$object_status['status']],
);
drupal_set_message(filter_xss(format_string('!summary !description', $here_params)), 'warning');
}
else {
$object = islandora_add_object($object);
if ($object) {
drupal_set_message(t('@module: Successfully installed. !object_link.', array(
'@module' => $module_name,
drupal_set_message(filter_xss($t('@module: Successfully installed. !object_link.', array(
'!object_link' => $object_link,
)), 'status');
) + $t_params)), 'status');
}
else {
drupal_set_message(t('@module: Failed to install. @label.', array(
'@module' => $module_name,
drupal_set_message($t('@module: Failed to install. @label.', array(
'@label' => $label,
)), 'warning');
) + $t_params), 'warning');
}
}
}
@ -307,21 +328,20 @@ function islandora_install_solution_pack($module, $op = 'install') {
* directly for each solution pack.
*/
function islandora_uninstall_solution_pack($module) {
$t = get_t();
module_load_include('module', 'islandora', 'islandora');
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('module', $module, $module);
$config_link = l(t('Islandora configuration'), 'admin/islandora/configure');
$config_link = l($t('Islandora configuration'), 'admin/islandora/configure');
$info_file = drupal_get_path('module', $module) . "/{$module}.info";
$info_array = drupal_parse_info_file($info_file);
$module_name = $info_array['name'];
if (!islandora_describe_repository()) {
$msg = '@module: Did not uninstall any objects. Could not connect to the ';
$msg .= 'repository. Please check the settings on the !config_link page ';
$msg .= 'and uninstall the required objects manually if necessary.';
drupal_set_message(st($msg, array(
'@module' => $module_name,
'!config_link' => $config_link,
)), 'error');
$msg = $t('@module: Did not uninstall any objects. Could not connect to the repository. Please check the settings on the !config_link page and uninstall the required objects manually if necessary.', array(
'@module' => $module_name,
'!config_link' => $config_link,
));
drupal_set_message(filter_xss($msg), 'error');
return;
}
$connection = islandora_get_tuque_connection();
@ -334,19 +354,20 @@ function islandora_uninstall_solution_pack($module) {
};
$existing_objects = array_filter($objects, $filter);
foreach ($existing_objects as $object) {
$msg = '@module: Did not remove !object_link. It may be used by other sites.';
$object_link = l($object->label, "islandora/object/{$object->id}");
drupal_set_message(st($msg, array(
'!object_link' => $object_link,
'@module' => $module_name,
)), 'warning');
$msg = $t('@module: Did not remove !object_link. It may be used by other sites.', array(
'!object_link' => $object_link,
'@module' => $module_name,
));
drupal_set_message(filter_xss($msg), 'warning');
}
}
/**
* Function to check the status of an object against an object model array.
*
* @param NewFedoraObject $object_definition
* @param AbstractObject $object_definition
* A new fedora object that defines what the object should contain.
*
* @return string
@ -357,7 +378,7 @@ function islandora_uninstall_solution_pack($module) {
* @see islandora_solution_pack_form()
* @see islandora_install_solution_pack()
*/
function islandora_check_object_status(NewFedoraObject $object_definition) {
function islandora_check_object_status(AbstractObject $object_definition) {
$existing_object = islandora_object_load($object_definition->id);
if (!$existing_object) {
return array('status' => 'missing', 'status_friendly' => t('Missing'));
@ -606,7 +627,7 @@ function theme_islandora_viewers_table($variables) {
* Array or string with data the module needs in order to render a full viewer
* @param string $variable_id
* The id of the Drupal variable the viewer settings are saved in
* @param FedoraObject $fedora_object
* @param AbstractObject $fedora_object
* The tuque object representing the fedora object being displayed
*
* @return string

26
includes/tuque_wrapper.inc

@ -34,23 +34,21 @@ $islandora_module_path = drupal_get_path('module', 'islandora');
/**
* Allow modules to alter an object before a mutable event occurs.
*/
function islandora_alter_object(AbstractFedoraObject $object, array &$context) {
$types = array('islandora_object');
foreach ($object->models as $model) {
$types[] = "{$model}_islandora_object";
}
drupal_alter($types, $object, $context);
function islandora_alter_object(AbstractObject $object, array &$context) {
module_load_include('inc', 'islandora', 'includes/utilities');
drupal_alter(islandora_build_hook_list('islandora_object', $object->models), $object, $context);
}
/**
* Allow modules to alter a datastream before a mutable event occurs.
*/
function islandora_alter_datastream(AbstractFedoraObject $object, AbstractDatastream $datastream, array &$context) {
$types = array('islandora_datastream');
function islandora_alter_datastream(AbstractObject $object, AbstractDatastream $datastream, array &$context) {
module_load_include('inc', 'islandora', 'includes/utilities');
$types = array();
foreach ($object->models as $model) {
$types[] = "{$model}_{$datastream->id}_islandora_datastream";
$types[] = "{$model}_{$datastream->id}";
}
drupal_alter($types, $object, $datastream, $context);
drupal_alter(islandora_build_hook_list('islandora_datastream', $types), $object, $datastream, $context);
}
/**
@ -207,7 +205,7 @@ class IslandoraFedoraApiM extends FedoraApiM {
}
return $ret;
}
catch(Exception $e) {
catch (Exception $e) {
watchdog('islandora', 'Failed to modify datastream @dsid from @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@dsid' => $dsid,
@ -241,7 +239,7 @@ class IslandoraFedoraApiM extends FedoraApiM {
}
return $ret;
}
catch(Exception $e) {
catch (Exception $e) {
watchdog('islandora', 'Failed to modify object: @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@code' => $e->getCode(),
@ -283,7 +281,7 @@ class IslandoraFedoraApiM extends FedoraApiM {
return $ret;
}
}
catch(Exception $e) {
catch (Exception $e) {
watchdog('islandora', 'Failed to purge datastream @dsid from @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@dsid' => $dsid,
@ -327,7 +325,7 @@ class IslandoraFedoraApiM extends FedoraApiM {
return $ret;
}
}
catch(Exception $e) {
catch (Exception $e) {
watchdog('islandora', 'Failed to purge object @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@code' => $e->getCode(),

263
includes/utilities.inc

@ -204,13 +204,13 @@ function islandora_escape_pid_for_function($pid) {
// Apparently, case doesn't matter for function calls in PHP, so let's not
// really worry about changing the case.
return str_replace(
// Any PID characters which are not valid in the name of a PHP function.
array(
':',
'-',
),
'_',
$pid
// Any PID characters which are not valid in the name of a PHP function.
array(
':',
'-',
),
'_',
$pid
);
}
@ -256,8 +256,8 @@ function islandora_get_namespace($id) {
*/
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: '));
$namespace = islandora_get_namespace($id);
$allowed_namespaces = islandora_get_allowed_namespaces();
return in_array($namespace, $allowed_namespaces);
}
return TRUE;
@ -271,14 +271,14 @@ function islandora_namespace_accessible($id) {
* This function gets its info from the RELS-EXT directly rather than through an
* risearch.
*
* @param FedoraObject $object
* @param AbstractObject $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) {
function islandora_get_parents_from_rels_ext(AbstractObject $object) {
try {
$collections = array_merge(
$object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOfCollection'),
@ -298,7 +298,7 @@ function islandora_get_parents_from_rels_ext(FedoraObject $object) {
/**
* Gets the datastreams requirments that are missing.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object which models will be used to determine what datastreams it
* should have.
*
@ -306,7 +306,7 @@ function islandora_get_parents_from_rels_ext(FedoraObject $object) {
* 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) {
function islandora_get_missing_datastreams_requirements(AbstractObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
$datastreams = islandora_get_datastreams_requirements($object);
foreach ($datastreams as $dsid => $requirements) {
@ -331,7 +331,7 @@ function islandora_get_missing_datastreams_requirements(FedoraObject $object) {
*
* @see islandora_get_required_datastreams_from_content_model()
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object which models will be used to determine what datastreams it
* should have.
*
@ -339,7 +339,7 @@ function islandora_get_missing_datastreams_requirements(FedoraObject $object) {
* The DS-COMPOSITE-MODEL defined datastreams that are required for the given
* object.
*/
function islandora_get_datastreams_requirements(FedoraObject $object) {
function islandora_get_datastreams_requirements(AbstractObject $object) {
return islandora_get_datastreams_requirements_from_models($object->models);
}
@ -375,26 +375,21 @@ function islandora_get_datastreams_requirements_from_models(array $models) {
*
* @todo Add support for fetching the schema information.
*
* @param FedoraObject $object
* @param AbstractObject $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
* An associative array mapping datastream IDs to associative arrays
* containing the values parsed from the DS-COMPOSITE-MODEL on the given
* object--of the form:
* - DSID: A datastream ID being described.
* - "id": A string containing ID of the datastream.
* - "mime": A array containing MIME-types the stream may have.
* - "optional": A boolean indicating if the given stream is optional.
*/
function islandora_get_datastreams_requirements_from_content_model(FedoraObject $object) {
if (empty($object[DS_COMP_STREAM])) {
function islandora_get_datastreams_requirements_from_content_model(AbstractObject $object) {
if (empty($object[DS_COMP_STREAM]) || !islandora_datastream_access(FEDORA_VIEW_OBJECTS, $object[DS_COMP_STREAM])) {
return array();
}
$xml = new SimpleXMLElement($object[DS_COMP_STREAM]->content);
@ -465,20 +460,43 @@ function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastr
if (isset($ds['control_group']) && in_array($ds['control_group'], $groups)) {
$control_group = $ds['control_group'];
}
$ds_uri = FALSE;
$as_file = FALSE;
if (file_valid_uri($ds['datastream_file'])) {
// A local file with as a Drupal file/stream wrapper URI.
$datastream_file = $ds['datastream_file'];
$ds_uri = TRUE;
$as_file = TRUE;
}
elseif (is_readable($ds['datastream_file'])) {
// A local file as a filesystem path.
$datastream_file = drupal_realpath($ds['datastream_file']);
$as_file = TRUE;
}
else {
$datastream_file = url($ds['datastream_file'], array('absolute' => TRUE));
$scheme = parse_url($ds['datastream_file'], PHP_URL_SCHEME);
if (in_array($scheme, stream_get_wrappers())) {
// A URI which gets handled by one of the PHP-native stream wrappers.
$datastream_file = $ds['datastream_file'];
$as_file = TRUE;
}
else {
// Schema does not match available php stream wrapper. Attempt to
// set datastream_file by url for the given scheme. Https (SSL) can
// cause this to fail, and trigger an output log in watchdog.
$datastream_file = url($ds['datastream_file'], array('absolute' => TRUE));
watchdog('islandora',
'Attempting to ingest %file in islandora_prepare_new_object(), but it does not appear to be readable. We will pass the path through url(), and pass along as such.',
array('%file' => $datastream_file),
WATCHDOG_WARNING);
}
}
$datastream = $object->constructDatastream($dsid, $control_group);
$datastream->label = $label;
$datastream->mimetype = $mimetype;
switch ($control_group) {
case 'M':
if ($ds_uri) {
if ($as_file) {
$datastream->setContentFromFile($datastream_file);
}
else {
@ -490,8 +508,10 @@ function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastr
$datastream->setContentFromString(file_get_contents($datastream_file));
break;
}
$object->ingestDatastream($datastream);
}
return $object;
}
@ -505,8 +525,9 @@ function islandora_display_repository_inaccessible_message() {
$text = t('Islandora configuration');
$link = l($text, 'admin/islandora/configure', array('attributes' => array('title' => $text)));
$message = t('Could not connect to the repository. Please check the settings on the !link page.',
array('!link' => $link));
drupal_set_message($message, 'error', FALSE);
array('!link' => $link));
drupal_set_message(check_plain($message), 'error', FALSE);
}
/**
@ -595,35 +616,29 @@ function islandora_system_settings_form_default_value($name, $default_value, arr
/**
* Returns basic information about DS-COMPOSITE-MODEL.
*
* @deprecated
* The pre-existing--and more flexible--
* islandora_get_datastreams_requirements_from_content_model() should be
* preferred, as it addresses the case where a stream can be allowed to have
* one of a set of mimetypes (this functions appears to only return the last
* declared mimetype for a given datastream).
*
* @param string $pid
* PID of content model containing DS_COMP stream.
* The PID of content model containing DS_COMP stream.
*
* @return array
* array of values in the following form
*
* [DC] => Array
* (
* [mimetype] => text/xml
* )
*
* [MODS] => Array
* (
* [optional] => true
* [mimetype] => text/xml
* )
*
* [RELS-EXT] => Array
* (
* [mimetype] => application/rdf+xml
* )
*
* [RELS-INT] => Array
* (
* [optional] => true
* [mimetype] => application/rdf+xml
* )
* An associative array mapping datastream IDs to an associative array
* representing the parsed DS-COMPOSITE-MODEL of the form:
* - DSID: A string containing the datastream ID.
* - "mimetype": A string containing the last mimetype declared for the
* given datastream ID.
* - "optional": An optional boolean indicating that the given datastream
* is optional.
*/
function islandora_get_comp_ds_mappings($pid) {
$message = islandora_deprecated('7.x-1.2', t('Refactor to use the more flexible islandora_get_datastreams_requirements_from_content_model().'));
trigger_error(filter_xss($message), E_USER_DEPRECATED);
$cm_object = islandora_object_load($pid);
if (!isset($cm_object) || !isset($cm_object['DS-COMPOSITE-MODEL'])) {
return FALSE;
@ -658,6 +673,9 @@ function islandora_get_comp_ds_mappings($pid) {
* TRUE if the account has all the given permissions, FALSE otherwise.
*/
function islandora_user_access_all(array $perms, $account = NULL) {
$message = islandora_deprecated('7.x-1.2', 'Roll your own code or use islandora_user_access().');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
foreach ($perms as $perm) {
if (!user_access($perm, $account)) {
return FALSE;
@ -679,6 +697,9 @@ function islandora_user_access_all(array $perms, $account = NULL) {
* otherwise.
*/
function islandora_user_access_any(array $perms, $account = NULL) {
$message = islandora_deprecated('7.x-1.2', 'Roll your own code or use islandora_user_access().');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
foreach ($perms as $perm) {
if (user_access($perm, $account)) {
return TRUE;
@ -697,7 +718,13 @@ function islandora_get_allowed_namespaces() {
$matches = array();
$allowed_namespaces = variable_get('islandora_pids_allowed', 'default: demo: changeme: islandora:');
preg_match_all('/([A-Za-z0-9-\.]+):/', $allowed_namespaces, $matches);
return $matches[1];
$accessible_namespaces = $matches[1];
// Ensure that the "islandora" namespace is explicitly allowed
// no matter what happens.
if (!in_array('islandora', $accessible_namespaces)) {
$accessible_namespaces[] = 'islandora';
}
return $accessible_namespaces;
}
/**
@ -718,14 +745,24 @@ function islandora_get_allowed_namespaces() {
function islandora_get_content_models($ignore_system_namespace = TRUE) {
module_load_include('inc', 'islandora', 'includes/utilities');
$tuque = islandora_get_tuque_connection();
$query = 'select $object $label from <#ri>
where ($object <fedora-model:label> $label
and ($object <fedora-model:hasModel> <info:fedora/fedora-system:ContentModel-3.0>
or $object <fedora-rels-ext:isMemberOfCollection> <info:fedora/islandora:ContentModelsCollection>)
and $object <fedora-model:state> <info:fedora/fedora-system:def/model#Active>)
order by $label';
$query = "PREFIX fm: <" . FEDORA_MODEL_URI . ">
PREFIX fr: <" . FEDORA_RELS_EXT_URI . ">
SELECT ?object ?label
FROM <#ri>
WHERE {
{?object fm:hasModel <info:fedora/fedora-system:ContentModel-3.0>;
fm:state fm:Active
}
UNION{
?object fr:isMemberOfCollection <info:fedora/islandora:ContentModelsCollection>;
fm:state fm:Active
}
OPTIONAL{
?object fm:label ?label
}
}";
$content_models = array();
$results = $tuque->repository->ri->itqlQuery($query, 'unlimited');
$results = $tuque->repository->ri->sparqlQuery($query, 'unlimited');
foreach ($results as $result) {
$content_model = $result['object']['value'];
$label = $result['label']['value'];
@ -738,3 +775,93 @@ function islandora_get_content_models($ignore_system_namespace = TRUE) {
}
return $content_models;
}
/**
* Returns Drupal tableselect element allowing selection of Content Models.
*
* @param string $drupal_variable
* the name of the Drupal variable holding selected content models
* Content models held in this variable will appear at the top of
* the displayed list
* @param array $default_values_array
* default values to display if $drupal_variable is unset
*
* @return array
* Drupal form element allowing content model selection
*/
function islandora_content_model_select_table_form_element($drupal_variable, $default_values_array = array('')) {
$defaults = array();
$rows = array();
$content_models = array();
$options = islandora_get_content_models(TRUE);
foreach ($options as $option) {
$content_models[$option['pid']] = $option['label'];
}
$selected = array_values(variable_get($drupal_variable, $default_values_array));
$comparator = function ($a, $b) use ($selected) {
$a_val = $b_val = 0;
if (in_array($a, $selected)) {
$a_val = 1;
}
if (in_array($b, $selected)) {
$b_val = 1;
}
return $b_val - $a_val;
};
uksort($content_models, $comparator);
foreach ($content_models as $pid => $label) {
$rows[$pid] = array(
'pid' => $pid,
'title' => $label,
);
$defaults[$pid] = in_array($pid, $selected);
}
$header = array(
'pid' => array('data' => t('PID')),
'title' => array('data' => t('Content Model')),
);
// Build and return table element.
$element = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $rows,
'#default_value' => $defaults,
'#empty' => t("There are no content models in this Fedora Repository."),
);
return $element;
}
/**
* Convience function for generating a E_USER_DEPRECATED message.
*
* To utilitize this function pass the results to trigger_error() like so:
*
* @code
* $message = islandora_deprecated('7.x-1.1', t('Use more cowbell.'))
* trigger_error(filter_xss($message), E_USER_DEPRECATED)
* @endcode
*
* @param string $release
* The release the calling function was depreciated in.
* @param string $solution
* A message describing an alternative solution to the deprecated function.
* It's assumed to be already passed though the t() function.
*
* @return string
* The deprecated message.
*/
function islandora_deprecated($release, $solution = NULL) {
$bt = debug_backtrace();
assert($bt[0]['function'] == __FUNCTION__);
$function = $bt[1]['function'];
$message = t('@function() has been deprecated. As of @release, please update your code before the next release.', array(
'@function' => $function,
'@release' => $release,
));
if (isset($solution)) {
$message .= "<br/>\n" . $solution;
}
return $message;
}

192
islandora.api.php

@ -8,7 +8,7 @@
/**
* Generate a repository objects view.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object to display
* @param object $user
* The user accessing the object.
@ -29,7 +29,7 @@ function hook_islandora_view_object($object, $user, $page_number, $page_size) {
* Content models PIDs have colons and hyphens changed to underscores, to
* create the hook name.
*
* @param FedoraObject $object
* @param AbstractObject $object
* A Tuque FedoraObject
*
* @return array
@ -42,18 +42,31 @@ function hook_CMODEL_PID_islandora_view_object($object) {
/**
* Alter display output after it has been generated.
*
* @param FedoraObject $object
* A Tuque FedoraObject being operated on.
* @param AbstractObject $object
* A Tuque AbstractObject being operated on.
* @param array $rendered
* An arr of rendered views.
* The array of rendered views.
*/
function hook_islandora_view_object_alter(&$object, &$rendered) {
}
/**
* Alter display output if the object has the given model.
*
* @see hook_islandora_view_object_alter()
*
* @param AbstractObject $object
* A Tuque AbstractObject being operated on.
* @param array $rendered
* The array of rendered views.
*/
function hook_CMODEL_PID_islandora_view_object_alter(&$object, &$rendered) {
}
/**
* Generate an object's management display.
*
* @param FedoraObject $object
* @param AbstractObject $object
* A Tuque FedoraObject
*
* @return array
@ -68,7 +81,7 @@ function hook_islandora_edit_object($object) {
* Content models PIDs have colons and hyphens changed to underscores, to
* create the hook name.
*
* @param FedoraObject $object
* @param AbstractObject $object
* A Tuque FedoraObject
*
* @return array
@ -80,7 +93,7 @@ function hook_CMODEL_PID_islandora_edit_object($object) {
/**
* Allow management display output to be altered.
*
* @param FedoraObject $object
* @param AbstractObject $object
* A Tuque FedoraObject
* @param array $rendered
* an arr of rendered views
@ -97,7 +110,7 @@ function hook_islandora_edit_object_alter(&$object, &$rendered) {
* Changing object properties such as "label", or "state", are considered
* modifications, where as manipulating an object's datstreams are not.
*
* @param AbstractFedoraObject $object
* @param AbstractObject $object
* The object to alter.
* @param array $context
* An associative array containing:
@ -117,7 +130,7 @@ function hook_islandora_edit_object_alter(&$object, &$rendered) {
*
* @see FedoraApiM::modifyObject()
*/
function hook_islandora_object_alter(AbstractFedoraObject $object, array &$context) {
function hook_islandora_object_alter(AbstractObject $object, array &$context) {
}
/**
@ -125,7 +138,7 @@ function hook_islandora_object_alter(AbstractFedoraObject $object, array &$conte
*
* @see hook_islandora_object_alter()
*/
function hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context) {
function hook_CMODEL_PID_islandora_object_alter(AbstractObject $object, array &$context) {
}
/**
@ -138,15 +151,15 @@ function hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, ar
* immediately, instead it will be triggered for all datastreams at the time
* of the NewFedoraObject's ingest.
*
* Purging datastreams from a NewFedoraObject will not trigger this alter hook
* Purging datastreams from a AbstractObject will not trigger this alter hook
* at all.
*
* Changing datastream's properties such as "label", or "state", are considered
* modifications, as well as changing the datastreams content.
*
* @param AbstractFedoraObject $object
* @param AbstractObject $object
* The object to the datastream belong to.
* @param AbstractFedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to alter.
* @param array $context
* An associative array containing:
@ -166,7 +179,7 @@ function hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, ar
*
* @see FedoraApiM::modifyDatastream()
*/
function hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) {
function hook_islandora_datastream_alter(AbstractObject $object, AbstractDatastream $datastream, array &$context) {
}
/**
@ -174,7 +187,7 @@ function hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractF
*
* @see hook_islandora_datastream_alter()
*/
function hook_CMODEL_PID_DSID_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) {
function hook_CMODEL_PID_DSID_islandora_datastream_alter(AbstractObject $object, AbstractDatastream $datastream, array &$context) {
}
/**
@ -187,10 +200,10 @@ function hook_CMODEL_PID_DSID_islandora_datastream_alter(AbstractFedoraObject $o
* If ingested directly via the FedoraApiM object this will not be called as we
* don't have access to the ingested object at that time.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object that was ingested.
*/
function hook_islandora_object_ingested(FedoraObject $object) {
function hook_islandora_object_ingested(AbstractObject $object) {
}
/**
@ -198,7 +211,7 @@ function hook_islandora_object_ingested(FedoraObject $object) {
*
* @see hook_islandora_object_ingested()
*/
function hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object) {
function hook_CMODEL_PID_islandora_object_ingested(AbstractObject $object) {
}
/**
@ -209,13 +222,13 @@ function hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object) {
* Changing object properties such as "label", or "state", are considered
* modifications, where as manipulating an object's datstreams are not.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object that was ingested.
*
* @todo We should also include what changes were made in a additional
* parameter.
*/
function hook_islandora_object_modified(FedoraObject $object) {
function hook_islandora_object_modified(AbstractObject $object) {
}
/**
@ -223,7 +236,7 @@ function hook_islandora_object_modified(FedoraObject $object) {
*
* @see hook_islandora_object_modified()
*/
function hook_CMODEL_PID_islandora_object_modified(FedoraObject $object) {
function hook_CMODEL_PID_islandora_object_modified(AbstractObject $object) {
}
/**
@ -255,12 +268,12 @@ function hook_CMODEL_PID_islandora_object_purged($pid) {
* If ingested directly via the FedoraApiM object this will not be called as we
* don't have access to the ingested datastream at that time.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object the datastream belongs to.
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The ingested datastream.
*/
function hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) {
function hook_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) {
}
/**
@ -268,7 +281,7 @@ function hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastre
*
* @see hook_islandora_object_ingested()
*/
function hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) {
function hook_CMODEL_PID_DSID_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) {
}
/**
@ -279,23 +292,23 @@ function hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object
* Changing datastream properties such as "label", or "state", are considered
* modifications, as well as the datastreams content.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object the datastream belongs to.
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream that was ingested.
*
* @todo We should also include what changes were made in a additional
* parameter.
*/
function hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) {
function hook_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) {
}
/**
* Notify modules that the given datastream was ingested.
* Notify modules that the given datastream was modified.
*
* @see hook_islandora_datastream_modified()
*/
function hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) {
function hook_CMODEL_PID_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) {
}
/**
@ -304,12 +317,12 @@ function hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, Fed
* This hook is called after an datastream has been successfully purged, or
* when its state has been changed to "Deleted".
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object the datastream belonged to.
* @param string $dsid
* The ID of the datastream that was purged/deleted.
*/
function hook_islandora_datastream_purged(FedoraObject $object, $dsid) {
function hook_islandora_datastream_purged(AbstractObject $object, $dsid) {
}
/**
@ -317,13 +330,13 @@ function hook_islandora_datastream_purged(FedoraObject $object, $dsid) {
*
* @see hook_islandora_datastream_purged()
*/
function hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid) {
function hook_CMODEL_PID_islandora_datastream_purged(AbstractObject $object, $dsid) {
}
/**
* Register a datastream edit route/form.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object to check.
* @param string $dsid
* todo
@ -373,15 +386,26 @@ function hook_islandora_undeletable_datastreams(array $models) {
* @return array
* An associative array of associative arrays which define each step in the
* ingest process. Each step should consist of a unique name mapped to an
* array 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.
* array of properties (keys) which take different paramaters based upon type:
* - type: Type of step. Only "form" and "callback" are implemented so far.
* Required "form" type specific parameters:
* - 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:
* Required "callback" type specific parameters:
* - do_function: An associate array including:
* - 'function': The callback function to be called.
* - 'args': An array of arguments to pass to the callback function.
* - undo_function: An associate array including:
* - 'function': The callback function to be called to reverse the
* executed action in the ingest steps.
* - 'args': An array of arguments to pass to the callback function.
* Shared parameters between both types:
* - weight: The "weight" of this step--heavier(/"larger") values sink to the
* end of the process while smaller(/"lighter") values are executed first.
* Both types may optionally include:
* - module: A module from which we want to load an include.
* "Form" type may optionally include:
* - file: A file to include (relative to the module's path, including the
* file's extension).
*/
@ -393,6 +417,18 @@ function hook_islandora_ingest_steps(array $form_state) {
'form_id' => 'my_cool_form',
'args' => array('arg_one', 'numero deux'),
),
'my_cool_step_callback' => array(
'type' => 'callback',
'weight' => 2,
'do_function' => array(
'function' => 'my_cool_execute_function',
'args' => array('arg_one', 'numero deux'),
),
'undo_function' => array(
'function' => 'my_cool_undo_function',
'args' => array('arg_one', 'numero deux'),
),
),
);
}
/**
@ -407,3 +443,79 @@ function hook_islandora_ingest_steps(array $form_state) {
*/
function hook_CMODEL_PID_islandora_ingest_steps(array $form_state) {
}
/**
* Object-level access callback hook.
*
* @param string $op
* A string define an operation to check. Should be defined via
* hook_permission().
* @param AbstractObject $object
* An object to check the operation on.
* @param object $user
* A loaded user object, as the global $user variable might contain.
*
* @return bool|NULL
* Either boolean TRUE or FALSE to explicitly allow or deny the operation on
* the given object, or NULL to indicate that we are making no assertion
* about the outcome.
*/
function hook_islandora_object_access($op, $object, $user) {
switch ($op) {
case 'create stuff':
return TRUE;
case 'break stuff':
return FALSE;
case 'do a barrel roll!':
return NULL;
}
}
/**
* Content model specific version of hook_islandora_object_access().
*
* @see hook_islandora_object_access()
*/
function hook_CMODEL_PID_islandora_object_access($op, $object, $user) {
}
/**
* Datastream-level access callback hook.
*
* @param string $op
* A string define an operation to check. Should be defined via
* hook_permission().
* @param AbstractDatastream $object
* An object to check the operation on.
* @param object $user
* A loaded user object, as the global $user variable might contain.
*
* @return bool|NULL
* Either boolean TRUE or FALSE to explicitly allow or deny the operation on
* the given object, or NULL to indicate that we are making no assertion
* about the outcome.
*/
function hook_islandora_datastream_access($op, $object, $user) {
switch ($op) {
case 'create stuff':
return TRUE;
case 'break stuff':
return FALSE;
case 'do a barrel roll!':
return NULL;
}
}
/**
* Content model specific version of hook_islandora_datastream_access().
*
* @see hook_islandora_datastream_access()
*/
function hook_CMODEL_PID_islandora_datastream_access($op, $object, $user) {
}

4
islandora.info

@ -11,8 +11,10 @@ files[] = includes/dublin_core.inc
files[] = includes/tuque.inc
files[] = includes/tuque_wrapper.inc
files[] = includes/object.entity_controller.inc
files[] = tests/web_test_case.inc
files[] = tests/islandora_web_test_case.inc
files[] = tests/authtokens.test
files[] = tests/hooks.test
files[] = tests/ingest.test
files[] = tests/hooked_access.test
files[] = tests/islandora_manage_permissions.test
php = 5.3

5
islandora.install

@ -10,13 +10,14 @@
*/
function islandora_requirements($phase) {
$requirements = array();
// Ensure translations don't break at install time
// Ensure translations don't break at install time.
$t = get_t();
if (!class_exists('XSLTProcessor', FALSE)) {
$requirements['islandora_xsltprocessor']['title'] = $t('Islandora XSLTProcessor Prerequisite');
$requirements['islandora_xsltprocessor']['value'] = $t('Not installed');
$link = l($t('PHP XSL extension'), 'http://us2.php.net/manual/en/book.xsl.php', array('attributes' => array('target'=>'_blank')));
$link = l($t('PHP XSL extension'), 'http://us2.php.net/manual/en/book.xsl.php', array('attributes' => array('target' => '_blank')));
$requirements['islandora_xsltprocessor']['description'] = $t('The !xsllink is required. Check your installed PHP extensions and php.ini file.', array('!xsllink' => $link));
$requirements['islandora_xsltprocessor']['severity'] = REQUIREMENT_ERROR;
}

491
islandora.module

@ -52,6 +52,9 @@ define('ISLANDORA_DATASTREAM_MODIFIED_HOOK', 'islandora_datastream_modified');
define('ISLANDORA_DATASTREAM_PURGED_HOOK', 'islandora_datastream_purged');
define('ISLANDORA_INGEST_STEP_HOOK', 'islandora_ingest_steps');
// Autocomplete paths.
define('ISLANDORA_CONTENT_MODELS_AUTOCOMPLETE', 'islandora/autocomplete/content-models');
/**
* Implements hook_menu().
*
@ -91,7 +94,8 @@ function islandora_menu() {
'access arguments' => array(FEDORA_VIEW_OBJECTS),
);
$items['islandora/object/%islandora_object'] = array(
'title' => 'Repository',
'title callback' => 'islandora_drupal_title',
'title arguments' => array(2),
'page callback' => 'islandora_view_object',
'page arguments' => array(2),
'type' => MENU_NORMAL_ITEM,
@ -120,7 +124,7 @@ function islandora_menu() {
FEDORA_METADATA_EDIT,
FEDORA_ADD_DS,
FEDORA_PURGE,
FEDORA_INGEST
FEDORA_INGEST,
), 2),
);
@ -187,8 +191,8 @@ function islandora_menu() {
'page arguments' => array(4, FALSE),
'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc',
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_VIEW_OBJECTS, 2, 4),
'access callback' => 'islandora_datastream_access',
'access arguments' => array(FEDORA_VIEW_OBJECTS, 4),
'load arguments' => array(2),
);
// This menu item uses token authentication in islandora_tokened_object.
@ -205,8 +209,8 @@ function islandora_menu() {
'page arguments' => array(4),
'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc',
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_VIEW_OBJECTS, 2, 4),
'access callback' => 'islandora_datastream_access',
'access arguments' => array(FEDORA_VIEW_OBJECTS, 4),
'load arguments' => array(2),
);
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/edit'] = array(
@ -215,8 +219,8 @@ function islandora_menu() {
'page arguments' => array(4),
'type' => MENU_CALLBACK,
'file' => 'includes/datastream.inc',
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_METADATA_EDIT, 2, 4),
'access callback' => 'islandora_datastream_access',
'access arguments' => array(FEDORA_METADATA_EDIT, 4),
'load arguments' => array(2),
);
$items['islandora/object/%islandora_object/datastream/%islandora_datastream/delete'] = array(
@ -225,8 +229,8 @@ function islandora_menu() {
'page arguments' => array('islandora_delete_datastream_form', 4),
'file' => 'includes/delete_datastream.form.inc',
'type' => MENU_CALLBACK,
'access callback' => 'islandora_object_datastream_access_callback',
'access arguments' => array(FEDORA_PURGE, 2, 4),
'access callback' => 'islandora_datastream_access',
'access arguments' => array(FEDORA_PURGE, 4),
'load arguments' => array(2),
);
$items['islandora/object/%islandora_object/print'] = array(
@ -234,16 +238,26 @@ function islandora_menu() {
'page callback' => 'islandora_print_object',
'page arguments' => array(2),
'type' => MENU_CALLBACK,
'access callback' => 'islandora_object_access_callback',
'access callback' => 'islandora_object_access',
'access arguments' => array(FEDORA_VIEW_OBJECTS, 2),
'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),
$items['islandora/object/%islandora_object/download_clip'] = array(
'page callback' => 'islandora_download_clip',
'page arguments' => array(2),
'type' => MENU_CALLBACK,
'access callback' => 'islandora_object_access',
'access arguments' => array(FEDORA_VIEW_OBJECTS, 2),
'load arguments' => array(2),
);
$items[ISLANDORA_CONTENT_MODELS_AUTOCOMPLETE] = array(
'title' => 'Autocomplete callback',
'description' => 'Autocomplete a Fedora content model PID.',
'file' => 'includes/content_model.autocomplete.inc',
'page callback' => 'islandora_content_model_autocomplete',
'page arguments' => array(3),
'access arguments' => array('administer site configuration'),
'type' => MENU_CALLBACK,
);
return $items;
}
@ -286,6 +300,45 @@ function islandora_theme() {
'file' => 'theme/theme.inc',
'variables' => array('object' => NULL, 'content' => array()),
),
// Render a bunch of objects as either a grid or a list.
'islandora_objects' => array(
'file' => 'theme/theme.inc',
'template' => 'theme/islandora-objects',
'variables' => array(
'objects' => NULL,
'display' => NULL,
'page_size' => 20,
'limit' => 10,
),
),
// Render a bunch of objects as a grid.
'islandora_objects_grid' => array(
'file' => 'theme/theme.inc',
'template' => 'theme/islandora-objects-grid',
'variables' => array('objects' => NULL),
),
// Render a bunch of objects as a list.
'islandora_objects_list' => array(
'file' => 'theme/theme.inc',
'template' => 'theme/islandora-objects-list',
'variables' => array('objects' => NULL),
),
'islandora_datastream_edit_link' => array(
'file' => 'theme/theme.inc',
'variables' => array('datastream' => NULL),
),
'islandora_datastream_delete_link' => array(
'file' => 'theme/theme.inc',
'variables' => array('datastream' => NULL),
),
'islandora_datastream_view_link' => array(
'file' => 'theme/theme.inc',
'variables' => array('datastream' => NULL),
),
'islandora_datastream_download_link' => array(
'file' => 'theme/theme.inc',
'variables' => array('datastream' => NULL),
),
);
}
@ -334,6 +387,120 @@ function islandora_forms($form_id) {
return $forms;
}
/**
* Checks whether the user can access the given object.
*
* Checks for repository access, object/datastream existance, namespace access,
* user permissions, content models.
*
* Will check the given user or the user repersented by the GET token parameter,
* failing that it will use the global user.
*
* @global $user
*
* @param mixed $object_or_datastream
* The AbstractObject or AbstractDatastream to test for accessibility, if NULL
* is given the object is assumed to not exist or be inaccessible.
* @param array $permissions
* The required user permissions.
* @param array $content_models
* The required content models.
* @param bool $access_any
* (optional) TRUE to grant access if any single requirement is met from both
* the permissions and content models parameters. FALSE if all requirements
* must be met from both the permissions and content model parameters.
* @param object $user
* (optional) The account to check, if not given check the GET parameters for
* a token to restore the user. If no GET parameter is present use currently
* logged in user.
*
* @return bool
* TRUE if the user is allowed to access this object/datastream, FALSE
* otherwise.
*/
function islandora_user_access($object_or_datastream, array $permissions, $content_models = array(), $access_any = TRUE, $user = NULL) {
module_load_include('inc', 'islandora', 'includes/utilities');
$is_repository_accessible = &drupal_static(__FUNCTION__);
// If the repository is inaccessible then access always fails.
if (!isset($is_repository_accessible)) {
$is_repository_accessible = islandora_describe_repository();
if (!$is_repository_accessible) {
// Only display the inaccessible message once.
islandora_display_repository_inaccessible_message();
return FALSE;
}
}
if (!$is_repository_accessible || !is_object($object_or_datastream) || empty($permissions)) {
return FALSE;
}
// Determine what has been passed as $object.
if (is_subclass_of($object_or_datastream, 'AbstractObject')) {
$object = $object_or_datastream;
$datastream = NULL;
}
elseif (is_subclass_of($object_or_datastream, 'AbstractDatastream')) {
$datastream = $object_or_datastream;
$object = $datastream->parent;
}
// Determine the user account to test against.
if (!isset($user)) {
$token = filter_input(INPUT_GET, 'token', FILTER_SANITIZE_STRING);
if ($token) {
module_load_include('inc', 'islandora', 'includes/authtokens');
$token_user = islandora_validate_object_token($object->id, $datastream->id, $token);
if ($user) {
$user = user_load($token_user->uid);
}
}
else {
global $user;
}
}
// Check for access.
if ($access_any) {
$has_required_content_models = empty($content_models) ? TRUE : count(array_intersect($object->models, $content_models)) > 0;
if ($has_required_content_models) {
foreach ($permissions as $p) {
if ($datastream !== NULL) {
$check = islandora_datastream_access($p, $datastream, $user);
}
else {
$check = islandora_object_access($p, $object, $user);
}
if ($check) {
return TRUE;
}
}
return FALSE;
}
}
else {
$has_required_content_models = count(array_diff($content_models, $object->models)) == 0;
if ($has_required_content_models) {
foreach ($permissions as $p) {
if ($datastream !== NULL) {
$check = islandora_datastream_access($p, $datastream, $user);
}
else {
$check = islandora_object_access($p, $object, $user);
}
if (!$check) {
return FALSE;
}
}
// Should already have failed if there are no $permissions.
return TRUE;
}
}
return FALSE;
}
/**
* Checks whether the user can access the given object.
*
@ -342,7 +509,7 @@ function islandora_forms($form_id) {
*
* @param string $perm
* User permission to test for.
* @param FedoraObject $object
* @param AbstractObject $object
* The object to test, if NULL given the object doesn't exist or is
* inaccessible.
*
@ -357,7 +524,7 @@ function islandora_object_access_callback($perm, $object = NULL) {
return FALSE;
}
return user_access($perm) && is_object($object) && islandora_namespace_accessible($object->id);
return islandora_object_access($perm, $object);
}
/**
@ -368,10 +535,10 @@ function islandora_object_access_callback($perm, $object = NULL) {
*
* @param string $perm
* The user permission to test for.
* @param FedoraObject $object
* @param AbstractObject $object
* The object to test, if NULL given the object doesn't exist or is
* inaccessible.
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to test, if NULL given the datastream doesn't exist
* or is inaccessible.
* @param StdObject $account
@ -382,7 +549,10 @@ function islandora_object_access_callback($perm, $object = NULL) {
*/
function islandora_object_datastream_access_callback($perm, $object = NULL, $datastream = NULL, $account = NULL) {
module_load_include('inc', 'islandora', 'includes/utilities');
return user_access($perm, $account) && is_object($object) && islandora_namespace_accessible($object->id) && is_object($datastream);
$message = islandora_deprecated('7.x-1.2', 'Use islandora_datastream_access().');
trigger_error(filter_xss($message), E_USER_DEPRECATED);
return islandora_datastream_access($perm, $datastream, $account);
}
/**
@ -390,10 +560,8 @@ function islandora_object_datastream_access_callback($perm, $object = NULL, $dat
*
* This function will validate and use a token if present in the GET parameters.
*
* Checks for object existance, accessiblitly, namespace permissions,
* Checks for object existance, accessibility, namespace permissions,
* and user permissions
*
* @see islandora_object_datastream_tokened_access_callback()
*/
function islandora_object_datastream_tokened_access_callback($perm, $object = NULL, $datastream = NULL) {
module_load_include('inc', 'islandora', 'includes/utilities');
@ -408,7 +576,7 @@ function islandora_object_datastream_tokened_access_callback($perm, $object = NU
}
}
return islandora_object_datastream_access_callback($perm, $object, $datastream, $token_account);
return islandora_datastream_access($perm, $datastream, $token_account);
}
/**
@ -419,7 +587,7 @@ function islandora_object_datastream_tokened_access_callback($perm, $object = NU
*
* @param array $perms
* Array of user permission to test for.
* @param FedoraObject $object
* @param AbstractObject $object
* The object to test, if NULL given the object doesn't exist or is
* inaccessible.
*
@ -436,22 +604,22 @@ function islandora_object_manage_access_callback($perms, $object = NULL) {
$has_access = FALSE;
for ($i = 0; $i < count($perms) && !$has_access; $i++) {
$has_access = $has_access || user_access($perms[$i]);
$has_access = $has_access || islandora_object_access($perms[$i], $object);
}
return $has_access && is_object($object) && islandora_namespace_accessible($object->id);
return $has_access;
}
/**
* Renders the given objects manage overview page.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object to manage.
*
* @return string
* The HTML repersentation of the manage object page.
*/
function islandora_manage_overview_object(FedoraObject $object) {
function islandora_manage_overview_object(AbstractObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
$output = array();
foreach (islandora_build_hook_list(ISLANDORA_OVERVIEW_HOOK, $object->models) as $hook) {
@ -472,14 +640,14 @@ function islandora_manage_overview_object(FedoraObject $object) {
/**
* Renders the default manage object page for the given object.
*
* @param FedoraObject $object
* @param AbstractObject $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_manage_overview_object(FedoraObject $object) {
function islandora_default_islandora_manage_overview_object(AbstractObject $object) {
$output = theme('islandora_default_overview', array('islandora_object' => $object));
return array('Default overview output' => $output);
}
@ -493,13 +661,13 @@ function islandora_default_islandora_manage_overview_object(FedoraObject $object
* If no modules implement 'ISLANDORA_EDIT_HOOK' then this function returns the
* default manage view.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object to manage.
*
* @return string
* The HTML repersentation of the manage object page.
*/
function islandora_edit_object(FedoraObject $object) {
function islandora_edit_object(AbstractObject $object) {
module_load_include('inc', 'islandora', 'includes/breadcrumb');
module_load_include('inc', 'islandora', 'includes/utilities');
drupal_set_title($object->label);
@ -523,14 +691,14 @@ function islandora_edit_object(FedoraObject $object) {
/**
* Renders the default manage object page for the given object.
*
* @param FedoraObject $object
* @param AbstractObject $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(FedoraObject $object) {
function islandora_default_islandora_edit_object(AbstractObject $object) {
$output = theme('islandora_default_edit', array('islandora_object' => $object));
return array('Default Edit output' => $output);
}
@ -555,13 +723,13 @@ function islandora_view_default_object() {
* If no modules implement the hook then the default view object page
* will be rendered.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object to view.
*
* @return string
* The html repersentation of this object.
*/
function islandora_view_object(FedoraObject $object) {
function islandora_view_object(AbstractObject $object) {
module_load_include('inc', 'islandora', 'includes/breadcrumb');
module_load_include('inc', 'islandora', 'includes/utilities');
drupal_set_title($object->label);
@ -570,7 +738,8 @@ function islandora_view_object(FedoraObject $object) {
$page_number = (empty($_GET['page'])) ? '1' : $_GET['page'];
$page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize'];
$output = array();
foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $object->models) as $hook) {
$hooks = islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $object->models);
foreach ($hooks 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);
@ -583,14 +752,33 @@ function islandora_view_object(FedoraObject $object) {
$output = islandora_default_islandora_view_object($object);
}
arsort($output);
drupal_alter(ISLANDORA_VIEW_HOOK, $object, $output);
drupal_alter($hooks, $object, $output);
return implode('', $output);
}
/**
* Title callback for drupal title.
*
* Changes the drupal title to be the objects label.
* models that their modules want to provide a view for.
*
* @param AbstractObject $object
* The object to view.
*
* @return string
* The objects label.
*/
function islandora_drupal_title(AbstractObject $object) {
module_load_include('inc', 'islandora', 'includes/breadcrumb');
drupal_set_breadcrumb(islandora_get_breadcrumbs($object));
return $object->label;
}
/**
* Renders the default view object page for the given object.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object used to render the view object page.
*
* @return array
@ -742,7 +930,7 @@ function islandora_tokened_datastream_load($datastream_id, $map) {
*
* @param mixed $object_id
* The object to load the datastream from. This can be a Fedora PID or
* an instantiated IslandoraFedoraObject as it implements __toString()
* an instantiated IslandoraAbstractObject as it implements __toString()
* returning the PID.
*
* @return FedoraDatastream
@ -765,7 +953,7 @@ function islandora_datastream_load($datastream_id, $object_id) {
* attribute, as in:
* <content_model name="Collection" version="2" ...
*
* @param FedoraObject $object
* @param AbstractObject $object
* The Object the datastream belongs to.
* @param string $dsid
* The ID of the datastream.
@ -834,32 +1022,76 @@ function islandora_islandora_undeletable_datastreams(array $models) {
/**
* Ingest the given object.
*
* @param NewFedoraObject $object
* @param AbstractObject $object
* An ingestable FedoraObject.
*
* @return FedoraObject
* The ingested FedoraObject.
*/
function islandora_add_object(NewFedoraObject &$object) {
function islandora_add_object(AbstractObject &$object) {
return $object->repository->ingestObject($object);
}
/**
* Creates a new object with the same properties as the old.
*
* @todo Make Tuque objects support cloneing.
*
* @param AbstractObject $object
* An existing or new Fedora Object.
*
* @return AbstractObject
* The new Fedora Object with properties identical to the object given. This
* returned object is not automatically ingested.
*/
function islandora_copy_object(AbstractObject $object) {
$clone = $object->repository->constructObject($object->id);
$object_properties = array(
'state',
'createdDate',
'lastModifiedDate',
'label',
'owner',
'logMessage',
);
// Copy Properties.
foreach ($object_properties as $property) {
if (isset($object->$property)) {
$clone->$property = $object->$property;
}
}
// Copy Datastreams.
foreach ($object as $dsid => $datastream) {
if (empty($clone[$dsid])) {
$clone->ingestDatastream($datastream);
}
else {
// Get the content into a file, and add the file.
$temp_file = drupal_tempnam('temporary://', 'datastream');
$datastream->getContent($temp_file);
$clone[$dsid]->setContentFromFile($temp_file);
drupal_unlink($temp_file);
}
}
return $clone;
}
/**
* Delete's or purges the given object.
*
* @param FedoraObject $object
* @param AbstractObject $object
* An object to delete.
*
* @return bool
* TRUE if successful, FALSE otherwise.
*/
function islandora_delete_object(FedoraObject &$object) {
function islandora_delete_object(AbstractObject &$object) {
try {
$object->repository->purgeObject($object->id);
$object = NULL;
return TRUE;
}
catch(Exception $e) {
catch (Exception $e) {
// Exception message gets logged in Tuque Wrapper.
return FALSE;
}
@ -872,13 +1104,13 @@ function islandora_delete_object(FedoraObject &$object) {
* Which types are undefined, but more than likely because of the hooks
* there will be several kinds.
*
* @param FedoraDatastream $datastream
* @param AbstractDatastream $datastream
* The datastream to delete.
*
* @return bool
* TRUE if successful, FALSE otherwise.
*/
function islandora_delete_datastream(FedoraDatastream &$datastream) {
function islandora_delete_datastream(AbstractDatastream &$datastream) {
$object = $datastream->parent;
return $object->purgeDatastream($datastream->id);
}
@ -958,13 +1190,166 @@ function islandora_entity_property_info() {
* Modules can either implement preprocess functions to append content onto the
* 'content' variable, or override the display by providing a theme suggestion.
*
* @param FedoraObject $object
* @param AbstractObject $object
* The object.
*
* @return array
* A renderable array.
*/
function islandora_print_object(FedoraObject $object) {
function islandora_print_object(AbstractObject $object) {
drupal_set_title($object->label);
return theme('islandora_object_print', array('object' => $object));
}
/**
* Menu callback downloads the given clip.
*/
function islandora_download_clip(AbstractObject $object) {
if (isset($_GET['clip'])) {
$is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
$http_protocol = $is_https ? 'https' : 'http';
$url = $http_protocol . '://' . $_SERVER['HTTP_HOST'] . $_GET['clip'];
$filename = $object->label;
header("Content-Disposition: attachment; filename=\"{$filename}.jpg\"");
header("Content-type: image/jpeg");
header("Content-Transfer-Encoding: binary");
$ch = curl_init();
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
curl_close($ch);
}
exit();
}
/**
* Implements hook_file_mimetype_mapping_alter().
*
* Grab custom islandora mime type list
* and add any missing ext/mimes to the drupal mapping
*/
function islandora_file_mimetype_mapping_alter(&$mapping) {
$mime_detect = new MimeDetect();
$types = $mime_detect->getMimeTypes();
$diff = array_diff_key($types, $mapping['extensions']);
foreach ($diff as $ext => $mime) {
$mapping['mimetypes'][] = $mime;
end($mapping['mimetypes']);
$mapping['extensions'][$ext] = key($mapping['mimetypes']);
}
}
/**
* Hookable object access callback.
*
* @param string $op
* String identifying an operation to check. Should correspond to a
* permission declared via hook_permission().
* @param AbstractObject $object
* An object to check for permissions.
* @param object $user
* An optional loaded user object. Defaults to the global $user.
*
* @return bool
* TRUE if at least one implementation of hook_islandora_object_access()
* returned TRUE, and no implementation return FALSE; FALSE otherwise.
*/
function islandora_object_access($op, $object, $user = NULL) {
$cache = &drupal_static(__FUNCTION__);
if (!is_object($object)) {
// The object could not be loaded... Presumably, we don't have
// permission.
return FALSE;
}
if ($user === NULL) {
global $user;
}
// Populate the cache on a miss.
if (!isset($cache[$op][$object->id][$user->uid])) {
module_load_include('inc', 'islandora', 'includes/utilities');
$results = islandora_invoke_hook_list('islandora_object_access', $object->models, array(
$op,
$object,
$user,
));
// Nothing returned FALSE, and something returned TRUE.
$cache[$op][$object->id][$user->uid] = (!in_array(FALSE, $results, TRUE) && in_array(TRUE, $results, TRUE));
}
return $cache[$op][$object->id][$user->uid];
}
/**
* Implements hook_islandora_object_access().
*
* Denies according to PID namespace restrictions, then passes or denies
* according to core Drupal permissions according to user_access().
*/
function islandora_islandora_object_access($op, $object, $user) {
module_load_include('inc', 'islandora', 'includes/utilities');
return islandora_namespace_accessible($object->id) && user_access($op, $user);
}
/**
* Hookable access callback for datastreams.
*
* Requires the equivalent permissions on the object.
*/
function islandora_datastream_access($op, $datastream, $user = NULL) {
$cache = &drupal_static(__FUNCTION__);
if (!is_object($datastream)) {
// The object could not be loaded... Presumably, we don't have
// permission.
return NULL;
}
if ($user === NULL) {
global $user;
}
// Populate the cache on a miss.
if (!isset($cache[$op][$datastream->parent->id][$datastream->id][$user->uid])) {
module_load_include('inc', 'islandora', 'includes/utilities');
$object_results = islandora_invoke_hook_list('islandora_object_access', $datastream->parent->models, array(
$op,
$datastream->parent,
$user,
));
$datastream_results = islandora_invoke_hook_list('islandora_datastream_access', $datastream->parent->models, array(
$op,
$datastream,
$user,
));
// Neither the object nor the datastream check returned FALSE, and one in
// the object or datastream checks returned TRUE.
$cache[$op][$datastream->parent->id][$datastream->id][$user->uid] = (
!in_array(FALSE, $object_results, TRUE) &&
!in_array(FALSE, $datastream_results, TRUE) &&
(in_array(TRUE, $object_results, TRUE) || in_array(TRUE, $datastream_results, TRUE))
);
}
return $cache[$op][$datastream->parent->id][$datastream->id][$user->uid];
}
/**
* Implements hook_islandora_basic_collection_get_query_filters().
*/
function islandora_islandora_basic_collection_get_query_filters() {
$enforced = variable_get('islandora_namespace_restriction_enforced', FALSE);
if ($enforced) {
$namespace_array = islandora_get_allowed_namespaces();
$namespace_sparql = implode('|', $namespace_array);
return format_string('regex(str(?object), "info:fedora/(!namespaces):")', array(
'!namespaces' => $namespace_sparql,
));
}
}

6
islandora.rules.inc

@ -80,7 +80,7 @@ function islandora_rules_action_info() {
/**
* Checks that there is a relationship match on the given object.
*
* Takes a subject (either a FedoraObject or a FedoraDatastream), as well as
* Takes a subject (either a AbstractObject or a FedoraDatastream), as well as
* the parameters for FedoraRelsExt::get() or FedoraRelsInt::get(), to try to
* find a match.
*
@ -94,7 +94,7 @@ function islandora_object_has_relationship($sub, $pred_uri, $pred, $object, $typ
/**
* Remove a relationship from the given object.
*
* Takes a subject (either a FedoraObject or a FedoraDatastream), as well as
* Takes a subject (either a AbstractObject or a FedoraDatastream), as well as
* the parameters for FedoraRelsExt::remove() or FedoraRelsInt::remove(), to
* try to find a match.
*
@ -107,7 +107,7 @@ function islandora_object_remove_relationship($sub, $pred_uri, $pred, $object, $
/**
* Add a relationship to the given object.
*
* Takes a subject (either a FedoraObject or a FedoraDatastream), as well as
* Takes a subject (either a AbstractObject or a FedoraDatastream), as well as
* the parameters for FedoraRelsExt::add() or FedoraRelsInt::add(), and adds
* the represented relationship.
*

3
tests/README.txt → tests/README.md

@ -1,3 +1,4 @@
You can define your own configurations specific to your enviroment by copying
default.test_config.ini to test_config.ini, making your changes in the copied
file.
file. These test need write access to the system's $FEDORA_HOME/server/config
directory as well as the filter-drupal.xml file.

149
tests/hooked_access.test

@ -0,0 +1,149 @@
<?php
/**
* @file
* Tests to see if the hooks get called when appropriate.
*
* In the test module 'islandora_hooked_access_test' there are implementations
* of hooks being tested. These implementations modifies the session, and
* that's how we test if the hook gets called.
*
* To make sense of these tests reference islandora_hooked_access_test.module.
*/
class IslandoraHookedAccessTestCase extends IslandoraWebTestCase {
/**
* Gets info to display to describe this test.
*
* @see IslandoraWebTestCase::getInfo()
*/
public static function getInfo() {
return array(
'name' => 'Islandora Hooked Access Callback',
'description' => 'Ensure that the hooked access callback returns appropriate results.',
'group' => 'Islandora',
);
}
/**
* Creates an admin user and a connection to a fedora repository.
*
* @see IslandoraWebTestCase::setUp()
*/
public function setUp() {
parent::setUp('islandora_hooked_access_test');
$this->repository = $this->admin->repository;
$this->objects = array(
'test:testAccessHook',
);
$this->op = FEDORA_VIEW_OBJECTS;
$this->other_op = FEDORA_INGEST;
$this->denied_op = FEDORA_PURGE;
$this->purgeTestObjects();
$this->dsid = 'asdf';
$this->createTestObjects();
$this->object = $this->repository->getObject('test:testAccessHook');
}
/**
* Free any objects/resources created for this test.
*
* @see IslandoraWebTestCase::tearDown()
*/
public function tearDown() {
$this->purgeTestObjects();
unset($this->repository);
unset($_SESSION['islandora_hooked_access_test']);
parent::tearDown();
}
/**
* Create the test object(s) to use during the test.
*/
public function createTestObjects() {
foreach ($this->objects as $object_id) {
$object = $this->repository->constructObject($object_id);
$object->label = $object_id;
$datastream = $object->constructDatastream($this->dsid, 'M');
$datastream->label = 'fdsa';
$datastream->mimetype = 'text/plain';
$datastream->content = 'Some kinda awesome content stuffs...';
$object->ingestDatastream($datastream);
$this->repository->ingestObject($object);
}
}
/**
* Purge any objects created by the test's in this class.
*/
public function purgeTestObjects() {
foreach ($this->objects as $object) {
try {
$object = $this->repository->getObject($object);
$this->repository->purgeObject($object->id);
}
catch (Exception $e) {
// Meh... Either it didn't exist or the purge failed.
}
}
}
/**
* Deny an object permission check without an object.
*/
public function testDenyBadObject() {
$this->assertFalse(islandora_object_access($this->op, 'this is not an object'), 'Deny bad objects.');
}
/**
* Deny a datastream permission check without a datastream.
*/
public function testDenyBadDatastream() {
$this->assertFalse(islandora_datastream_access($this->op, 'this is not a datastream'), 'Deny bad datastreams.');
}
/**
* Allow operation on object.
*/
public function testAllowObject() {
$user = $this->drupalCreateUser(array($this->op));
$_SESSION['islandora_hooked_access_test'] = array(
$this->op,
$this->object,
$user,
);
$this->assertTrue(islandora_object_access($this->op, $this->object, $user), 'Allow object access.');
}
/**
* Allow operation on datastream.
*/
public function testAllowDatastream() {
$user = $this->drupalCreateUser(array($this->op));
$_SESSION['islandora_hooked_access_test'] = array(
$this->op,
$this->object['asdf'],
$user,
);
$this->assertTrue(islandora_datastream_access($this->op, $this->object['asdf'], $user), 'Allow datastream access.');
}
/**
* Deny an operation which was not explicitly allowed on an object.
*/
public function testDenyObjectExplicit() {
$this->assertFalse(islandora_object_access($this->denied_op, $this->object), 'Explicit denial of object access.');
}
/**
* Deny an operation which was not explicitly allowed on a datastream.
*/
public function testDenyDatastreamExplicit() {
$this->assertFalse(islandora_datastream_access($this->denied_op, $this->object['asdf']), 'Explicit denial of datastream access.');
}
}

12
tests/hooks.test

@ -32,7 +32,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
* @see IslandoraWebTestCase::setUp()
*/
public function setUp() {
parent::setUp('islandora_hooks_test', 'devel');
parent::setUp('islandora_hooks_test');
$this->repository = $this->admin->repository;
$this->purgeTestObjects();
}
@ -67,7 +67,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$object->label = "Don't Block";
$this->repository->purgeObject($object->id);
}
catch(Exception $e) {
catch (Exception $e) {
// Meh... Either it didn't exist or the purge failed.
}
}
@ -95,7 +95,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->fail('Blocked ingest should throw an Exception.');
$this->repository->purgeObject($object->id);
}
catch(Exception $e) {
catch (Exception $e) {
$this->pass('Ingest blocked and exception thrown.');
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called "hook_islandora_object_alter" when blocking ingesting via FedoraRepository::ingestObject.');
$this->assertFalse($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Did not called ISLANDORA_OBJECT_INGESTED_HOOK when blocking ingesting via FedoraRepository::ingestObject.');
@ -115,7 +115,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$object->label = 'block';
$this->fail('Blocked modify should throw an Exception.');
}
catch(Exception $e) {
catch (Exception $e) {
$this->pass('Modify blocked and exception thrown.');
$this->assertNotEqual($object->label, 'block', 'Modification did not stick.');
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called "hook_islandora_object_alter" when blocking modifying via set magic functions.');
@ -149,7 +149,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->repository->purgeObject($object->id);
$this->fail('Blocked modify should throw an Exception.');
}
catch(Exception $e) {
catch (Exception $e) {
$this->pass('Modify blocked and exception thrown.');
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when blocking purge via FedoraRepository::purgeObject.');
$this->assertFalse($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when blocking purge via FedoraRepository::purgeObject.');
@ -191,7 +191,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$ds->label = 'block';
$this->fail('Blocked modify should throw an Exception.');
}
catch(Exception $e) {
catch (Exception $e) {
$this->pass('Modify blocked and exception thrown.');
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called "hook_islandora_datastream_alter" when blocking modifying via set magic functions.');
$this->assertFALSE($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when blocking modifying via set magic functions.');

118
tests/ingest.test

@ -0,0 +1,118 @@
<?php
/**
* @file
* Tests to see if the hooks get called when appropriate.
*
* In the test module 'islandora_hooks_test' there are implementations
* of hooks being tested. These implementations modifies the session, and
* that's how we test if the hook gets called.
*
* To make sense of these tests reference islandora_hooks_test.module.
*/
class IslandoraIngestsTestCase extends IslandoraWebTestCase {
/**
* Gets info to display to describe this test.
*
* @see IslandoraWebTestCase::getInfo()
*/
public static function getInfo() {
return array(
'name' => 'Islandora Ingestion',
'description' => 'Ensure that the ingest forms function correctly.',
'group' => 'Islandora',
);
}
/**
* Creates an admin user and a connection to a fedora repository.
*
* @see IslandoraWebTestCase::setUp()
*/
public function setUp() {
parent::setUp('islandora_ingest_test');
$this->repository = $this->admin->repository;
$this->purgeTestObjects();
}
/**
* Free any objects/resources created for this test.
*
* @see IslandoraWebTestCase::tearDown()
*/
public function tearDown() {
$this->purgeTestObjects();
unset($this->repository);
parent::tearDown();
}
/**
* Purge any objects created by the test's in this class.
*/
public function purgeTestObjects() {
$objects = array(
'test:test',
);
foreach ($objects as $object) {
try {
$object = $this->repository->getObject($object);
$this->repository->purgeObject($object->id);
}
catch (Exception $e) {
// Meh... Either it didn't exist or the purge failed.
}
}
}
/**
* Test Ingest Steps.
*/
public function testIngest() {
// Login the Admin user.
$this->drupalLogin($this->admin);
// First step in form.
$this->drupalGet('test/ingest');
// Default model selected, has no additional steps.
$this->assertFieldByName('ingest', 'Ingest');
// Select a model with additional steps.
$edit = array(
'model' => 'test:testcmodel',
);
$this->drupalPostAJAX(NULL, $edit, 'model');
// Form now reflexts multiple steps.
$this->assertFieldByName('label', '');
$this->assertFieldByName('next', 'Next');
// Move to next step.
$edit = array(
'label' => 'foobar',
'model' => 'test:testcmodel',
);
$this->drupalPost(NULL, $edit, t('Next'));
$this->assertFieldByName('form_step_id', 'islandora_ingest_test_testcmodel');
$this->assertFieldByName('ingest', 'Ingest');
// Move back to first step.
$this->drupalPost(NULL, array(), t('Previous'));
// Try a different model that has an additional step.
$edit = array(
'model' => 'test:testcmodel2',
);
$this->drupalPostAJAX(NULL, $edit, 'model');
$edit = array(
'label' => 'foobar',
'model' => 'test:testcmodel2',
);
$this->drupalPost(NULL, $edit, t('Next'));
$this->assertFieldByName('form_step_id', 'islandora_ingest_test_testcmodel2');
$this->assertFieldByName('ingest', 'Ingest');
// Ingest the thing.
$this->drupalPost(NULL, array(), t('Ingest'));
// Test that the thing got made.
$object = islandora_object_load('test:test');
$this->assertEqual($object->label, 'foobar', 'Ingest Object matches submitted form values.');
$this->assertEqual($object->models, array('test:testcmodel2', 'fedora-system:FedoraObject-3.0'), 'Ingest Object matches submitted form values.');
}
}

7
tests/islandora_hooked_access_test.info

@ -0,0 +1,7 @@
name = Islandora Hooked Access Callback testing
description = Tests callback hooks. Do not enable.
core = 7.x
package = Testing
hidden = TRUE
files[] = islandora_hooks_test.module
dependencies[] = islandora

31
tests/islandora_hooked_access_test.module

@ -0,0 +1,31 @@
<?php
/**
* @file
* Hook implementations tested in hooked_access.test
*/
/**
* Implements hook_islandora_object_access().
*/
function islandora_hooked_access_test_islandora_object_access($op, $object, $user) {
if ($op == FEDORA_PURGE) {
return FALSE;
}
if (isset($_SESSION['islandora_hooked_access_test']) && $_SESSION['islandora_hooked_access_test'] === func_get_args()) {
return TRUE;
}
return NULL;
}
/**
* Implements hook_islandora_datastream_access().
*/
function islandora_hooked_access_test_islandora_datastream_access($op, $datastream, $user) {
if (isset($_SESSION['islandora_hooked_access_test']) && $_SESSION['islandora_hooked_access_test'] === func_get_args()) {
return TRUE;
}
return NULL;
}

3
tests/islandora_test.info → tests/islandora_hooks_test.info

@ -1,6 +1,7 @@
name = Islandora Test Module
name = Islandora Hook testing
description = Tests Hooks. Do not enable.
core = 7.x
package = Testing
hidden = TRUE
dependencies[] = islandora
files[] = islandora_hooks_test.module

14
tests/islandora_test.module → tests/islandora_hooks_test.module

@ -8,7 +8,7 @@
/**
* Implements hook_islandora_object_alter().
*/
function islandora_hooks_test_islandora_object_alter(AbstractFedoraObject $object, array &$context) {
function islandora_hooks_test_islandora_object_alter(AbstractObject $object, array &$context) {
switch ($context['action']) {
case 'ingest':
if ($object->id == 'test:testIngestedObjectHook') {
@ -54,7 +54,7 @@ function islandora_hooks_test_islandora_object_alter(AbstractFedoraObject $objec
/**
* Implements hook_islandora_object_alter().
*/
function islandora_hooks_test_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) {
function islandora_hooks_test_islandora_datastream_alter(AbstractObject $object, AbstractDatastream $datastream, array &$context) {
switch ($context['action']) {
case 'ingest':
if ($object->id == 'test:testIngestedDatastreamHook') {
@ -100,7 +100,7 @@ function islandora_hooks_test_islandora_datastream_alter(AbstractFedoraObject $o
/**
* Implements hook_islandora_object_ingested().
*/
function islandora_hooks_test_islandora_object_ingested(FedoraObject $object) {
function islandora_hooks_test_islandora_object_ingested(AbstractObject $object) {
if ($object->id == 'test:testIngestedObjectHook') {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK] = TRUE;
}
@ -109,7 +109,7 @@ function islandora_hooks_test_islandora_object_ingested(FedoraObject $object) {
/**
* Implements hook_islandora_object_modified().
*/
function islandora_hooks_test_islandora_object_modified(FedoraObject $object) {
function islandora_hooks_test_islandora_object_modified(AbstractObject $object) {
if ($object->id == 'test:testModifiedObjectHook') {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE;
}
@ -127,7 +127,7 @@ function islandora_hooks_test_islandora_object_purged($pid) {
/**
* Implements hook_islandora_datastream_ingested().
*/
function islandora_hooks_test_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) {
function islandora_hooks_test_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) {
if ($object->id == 'test:testIngestedDatastreamHook' && $datastream->id == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = TRUE;
}
@ -136,7 +136,7 @@ function islandora_hooks_test_islandora_datastream_ingested(FedoraObject $object
/**
* Implements hook_islandora_datastream_modified().
*/
function islandora_hooks_test_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) {
function islandora_hooks_test_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) {
if ($object->id == 'test:testModifiedDatastreamHook' && $datastream->id == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE;
}
@ -145,7 +145,7 @@ function islandora_hooks_test_islandora_datastream_modified(FedoraObject $object
/**
* Implements hook_islandora_datastream_purged().
*/
function islandora_hooks_test_islandora_datastream_purged(FedoraObject $object, $dsid) {
function islandora_hooks_test_islandora_datastream_purged(AbstractObject $object, $dsid) {
if ($object->id == 'test:testPurgedDatastreamHook' && $dsid == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE;
}

7
tests/islandora_ingest_test.info

@ -0,0 +1,7 @@
name = Islandora Testing
description = Required for testing islandora web-test case.
core = 7.x
package = Testing
hidden = TRUE
dependencies[] = islandora
files[] = islandora_test.module

166
tests/islandora_ingest_test.module

@ -0,0 +1,166 @@
<?php
/**
* @file
* Implements hooks that get tested by islandora_hooks.test
*/
/**
* Implements hook menu.
*/
function islandora_ingest_test_menu() {
return array(
'test/ingest' => array(
'title' => 'Ingest Form',
'page callback' => 'islandora_ingest_test_ingest',
'type' => MENU_LOCAL_ACTION,
'access callback' => TRUE,
),
);
}
/**
* Render the ingest form.
*/
function islandora_ingest_test_ingest() {
$connection = islandora_get_tuque_connection();
$object = $connection->repository->constructObject('test:test');
$object->label = 'New Object';
$configuration = array(
'objects' => array($object),
);
module_load_include('inc', 'islandora', 'includes/ingest.form');
return drupal_get_form('islandora_ingest_form', $configuration);
}
/**
* Implements hook_islandora_ingest_steps().
*/
function islandora_ingest_test_islandora_ingest_steps(array &$form_state) {
return array(
'islandora_ingest_test' => array(
'type' => 'form',
'form_id' => 'islandora_ingest_test_set_label_form',
'weight' => -50,
'module' => 'islandora_ingest_test',
),
);
}
/**
* Implements hook_MODEL_PID_islandora_ingest_steps().
*/
function islandora_ingest_test_test_testcmodel_islandora_ingest_steps(array &$form_state) {
return array(
'islandora_ingest_test_testcmodel' => array(
'type' => 'form',
'form_id' => 'islandora_ingest_test_testcmodel_form',
'weight' => -30,
'module' => 'islandora_ingest_test',
),
);
}
/**
* Implements hook_MODEL_PID_islandora_ingest_steps().
*/
function islandora_ingest_test_test_testcmodel2_islandora_ingest_steps(array &$form_state) {
return array(
'islandora_ingest_test_testcmodel2' => array(
'type' => 'form',
'form_id' => 'islandora_ingest_test_testcmodel2_form',
'weight' => -40,
'module' => 'islandora_ingest_test',
),
);
}
/**
* Sets the label of the ingestable object.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*
* @return array
* The Drupal form definition.
*/
function islandora_ingest_test_set_label_form(array $form, array &$form_state) {
$models = array('test:nomorestepscmodel', 'test:testcmodel', 'test:testcmodel2');
$model = isset($form_state['values']['model']) ? $form_state['values']['model'] : reset($models);
$shared_storage = &islandora_ingest_form_get_shared_storage($form_state);
$shared_storage['models'] = array($model);
return array(
'#prefix' => '<div id="islandora-select-content-model-wrapper">',
'#suffix' => '</div>',
'label' => array(
'#type' => 'textfield',
'#title' => t('Label'),
),
'model' => array(
'#type' => 'select',
'#title' => t('Select a Content Model to Ingest'),
'#options' => array_combine($models, $models),
'#default' => $model,
'#ajax' => array(
'callback' => 'islandora_ingest_test_model_ajax_callback',
'wrapper' => 'islandora-select-content-model-wrapper',
'method' => 'replace',
'effect' => 'fade',
),
),
);
}
/**
* Updates the model field.
*/
function islandora_ingest_test_model_ajax_callback(array $form, array &$form_state) {
return $form;
}
/**
* Sets the label of the ingestable object.
*
* @param array $form
* The Drupal form.
* @param array $form_state
* The Drupal form state.
*/
function islandora_ingest_test_set_label_form_submit(array $form, array &$form_state) {
$object = islandora_ingest_form_get_object($form_state);
$object->label = $form_state['values']['label'];
unset($object->models);
$object->models = array($form_state['values']['model']);
}
/**
* Test the First content model.
*/
function islandora_ingest_test_testcmodel_form(array $form, array &$form_state) {
return array(
);
}
/**
* Test the CModel submit.
*/
function islandora_ingest_test_testcmodel_form_submit(array $form, array &$form_state) {
}
/**
* Test the second content model.
*/
function islandora_ingest_test_testcmodel2_form(array $form, array &$form_state) {
return array(
);
}
/**
* Test the CModel submit.
*/
function islandora_ingest_test_testcmodel2_form_submit(array $form, array &$form_state) {
}

114
tests/islandora_manage_permissions.test

@ -1,7 +1,17 @@
<?php
/**
* @file
* Tests islandora permissions, and permission related funcitons.
*/
class IslandoraPermissionsTestCase extends IslandoraWebTestCase {
/**
* Gets info to display to describe this test.
*
* @see IslandoraWebTestCase::getInfo()
*/
public static function getInfo() {
return array(
'name' => 'Islandora Manage Permissions',
@ -10,69 +20,117 @@ class IslandoraPermissionsTestCase extends IslandoraWebTestCase {
);
}
/**
* Prepares enviroment for testing.
*
* @see IslandoraWebTestCase::setUp()
*/
public function setUp() {
parent::setUp(array('islandora'));
}
/**
* Test manage permissions.
*/
public function testManagePermissions() {
// permission FEDORA_VIEW_OBJECTS
// create a user with permission
// Test permission FEDORA_VIEW_OBJECTS.
// Create a user with permission.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS));
// log the user in
// Log the user in.
$this->drupalLogin($user);
$this->clickLink(t('Islandora Repository'));
$this->assertNoLink('Manage', 'Manage tab is not on current page.');
// permission FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES
// Test permission FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES));
// log the user in
$this->drupalLogin($user);
$this->clickLink(t('Islandora Repository'));
$this->assertLink('Manage', 0, 'Manage tab is on current page.');
$this->clickLink(t('Manage'));
$this->assertLink('Properties', 0, 'Properties tab is on current page.');
$this->assertNoLink('Datastreams', 'Datastreams tab is not on current page.');
$this->assertNoLink('Collection','Collection tab is not on current page.');
$this->assertNoLink('Collection', 'Collection tab is not on current page.');
// permission FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS
// Test permission FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS));
// log the user in
$this->drupalLogin($user);
$this->clickLink(t('Islandora Repository'));
$this->assertLink('Manage', 0, 'Manage tab is on current page.');
$this->clickLink(t('Manage'));
$this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.');
$this->assertNoLink('Properties', 'Properties tab is not on current page.');
$this->assertNoLink('Collection','Collection tab is not on current page.');
// permission FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT
$this->assertNoLink('Collection', 'Collection tab is not on current page.');
// Test permission FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT));
// log the user in
$this->drupalLogin($user);
$this->drupalLogin($user);
$this->clickLink(t('Islandora Repository'));
$this->assertLink('Manage', 0, 'Manage tab is on current page.');
$this->clickLink(t('Manage'));
$this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.');
$this->assertNoLink('Properties', 'Properties tab is not on current page.');
$this->assertNoLink('Collection','Collection tab is not on current page.');
// permission FEDORA_VIEW_OBJECTS, FEDORA_PURGE
$this->assertNoLink('Collection', 'Collection tab is not on current page.');
// Test permission FEDORA_VIEW_OBJECTS, FEDORA_PURGE.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE));
// log the user in
$this->drupalLogin($user);
$this->clickLink(t('Islandora Repository'));
$this->assertLink('Manage', 0, 'Manage tab is on current page.');
$this->clickLink(t('Manage'));
$this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.');
$this->assertNoLink('Properties', 'Properties tab is not on current page.');
$this->assertNoLink('Collection','Collection tab is not on current page.');
$this->assertNoLink('Collection', 'Collection tab is not on current page.');
}
}
/**
* Test generic access functions.
*
* Note that we can't test with the Global user as SimpleTest doesn't support
* it. Therefore we can't test the authtoken support.
*/
public function testAccessFunctions() {
$object = islandora_object_load(variable_get('islandora_repository_pid', 'islandora:root'));
// Test islandora_user_access().
// Test no object/permissions.
$ret = islandora_user_access(NULL, array());
$this->assertFalse($ret, 'User access denied when no object/permissions are provided.');
// Test with object no permissions.
$ret = islandora_user_access($object, array());
$this->assertFalse($ret, 'User access denied when no permissions are provided.');
// Test access with matching permission.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS));
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user);
$this->assertTrue($ret, 'User access granted when permissions match.');
// Test access with matching permission but access any is FALSE.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS));
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array(), FALSE, $user);
$this->assertFalse($ret, 'User access denied for matching permission but with access any set to FALSE.');
// Test access with non-matching permission.
$user = $this->drupalCreateUser(array(FEDORA_PURGE));
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user);
$this->assertFalse($ret, 'User access denied when permissions did not match.');
// Test access with both permissions and content model.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS));
$model = $object->models;
$model = reset($model);
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array($model), TRUE, $user);
$this->assertTrue($ret, 'User access granted for matching permission and model.');
// Test access with matching permissions and non-matching content model.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS));
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array('islandora:obviouslyNotACModel'), TRUE, $user);
$this->assertFalse($ret, 'User access denied for matching permission and non-matching model.');
// Test access with all matching permissions and one matching model but
// access any is FALSE.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE));
$model = $object->models;
$model = reset($model);
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array($model, 'islandora:obviouslyNotACModel'), FALSE, $user);
$this->assertFalse($ret, 'User access denied for all matching permissions and one matching model but with access any set to FALSE.');
$ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array($model), FALSE, $user);
$this->assertTrue($ret, 'User access granted for all matching permissions and matching models with access any set to FALSE.');
// Test passing in a Datastream.
$user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE));
$ret = islandora_user_access($object['DC'], array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user);
$this->assertTrue($ret, 'User access granted for matching permissions, with a datastream given instead of an object.');
}
}

130
tests/web_test_case.inc → tests/islandora_web_test_case.inc

@ -18,12 +18,17 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
// Always enable islandora.
$args[] = 'islandora';
parent::setUp($args);
// Its possible test are running before class autoloading.
module_load_include('inc', 'islandora', 'includes/tuque');
module_load_include('inc', 'islandora', 'includes/tuque_wrapper');
$this->configuration = $this->getTestConfiguration();
if ($this->configuration['use_drupal_filter']) {
$this->backUpDrupalFilter();
$this->setUpDrupalFilter();
}
$this->createAdminUser();
$this->admin = $this->createAdminUser();
}
/**
@ -85,15 +90,44 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
* Creates the a full fedora admin user with a repository connection.
*/
protected function createAdminUser() {
$this->admin = new stdClass();
$this->admin->uid = 1;
$this->admin->name = $this->configuration['admin_user'];
$this->admin->pass = $this->configuration['admin_pass'];
$roles = user_roles();
$index = array_search('administrator', $roles);
$user = $this->drupalCreateUser();
$user->roles[$index] = 'administrator';
$user->name = $this->configuration['admin_user'];
$user->pass = $this->configuration['admin_pass'];
$user = user_save($user);
$url = variable_get('islandora_base_url', $this->configuration['fedora_url']);
$connection = islandora_get_tuque_connection($this->admin, $url);
$this->admin->repository = $connection->repository;
return $this->admin;
$connection = islandora_get_tuque_connection($user, $url);
$user->repository = $connection->repository;
return $user;
}
/**
* Logs in the given user, handles the special case where the user is admin.
*
* @see DrupalWebTestCase::drupalLogin()
*/
protected function drupalLogin(stdClass $account) {
if ($account->uid == $this->admin->uid) {
// Create password for Drupal.
$edit = array('pass' => user_password());
$account = user_save($account, $edit);
// Raw password is used to login.
$account->pass_raw = $edit['pass'];
// We must login before changing the password for fedora.
parent::drupalLogin($account);
$account->name = $this->configuration['admin_user'];
$account->pass = $this->configuration['admin_pass'];
// Save the fedora admin credentials for later GET/POST requests.
$account = user_save($account);
}
else {
parent::drupalLogin($account);
}
}
/**
* Stores the content of the Drupal Filter for later restoration.
*/
@ -121,4 +155,84 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
unset($this->configuration);
parent::tearDown();
}
/**
* Asserts that the given datastreams exist on the object.
*
* @param AbstractObject $object
* The PID of the object
* @param array $datastreams
* An array of strings containing datastream names
*/
public function assertDatastreams($object, array $datastreams) {
if (!is_object($object)) {
$this->fail("Failed. Object passed in is invalid.");
return;
}
foreach ($datastreams as $datastream) {
if (isset($object[$datastream])) {
$this->pass("Loaded datastream {$datastream} from PID {$object->id}");
}
else {
$this->fail("Failed to load datastream {$datastream} from PID {$object->id}");
}
}
}
/**
* Gets a tuque object from a path.
*
* @param string $path
* A full or partial path to an islandora object.
*
* @return AbstractObject
* The pid of the object or FALSE if a PID is not found.
*/
public function getObjectFromPath($path) {
$path_parts = explode('/', $path);
$array_length = count($path_parts);
for ($i = 0; $i < $array_length; $i++) {
if ($path_parts[$i] == 'islandora' && isset($path_parts[$i + 1]) && $path_parts[$i + 1] == 'object') {
if (isset($path_parts[$i + 2])) {
return islandora_object_load(urldecode($path_parts[$i + 2]));
}
}
}
$this->fail("Failed to parse path : $path.");
return FALSE;
}
/**
* Deletes an object using the PID. This does the deletion using the UI.
*
* @param string $pid
* The PID of the collection to be deleted
*/
public function deleteObject($pid) {
$current_user = $this->loggedInUser;
$user = $this->drupalCreateUser(array(
'manage object properties',
'delete fedora objects and datastreams',
'view fedora repository objects',
));
$this->drupalLogin($user);
$path = 'islandora/object/' . $pid . '/manage/properties';
$edit = array();
$this->drupalPost($path, $edit, t('Delete'));
$this->drupalPost($this->url, $edit, t('Delete'));
$object = islandora_object_load($pid);
$this->drupalGet("islandora/object/$pid");
$this->assertResponse(404, "Object $pid successfully deleted.");
if ($current_user) {
$this->drupalLogin($current_user);
}
else {
$this->drupalLogout();
}
}
}

14
tests/scripts/line_endings.sh

@ -0,0 +1,14 @@
#!/bin/bash
RETURN=0
FILES=`find -L $1 -name "*.info" -o -name "*.txt" -o -name "*.md"`
echo "Testing for files with DOS line endings..."
for FILE in $FILES
do
file $FILE | grep CRLF
if [ $? == 0 ]
then
RETURN=1
fi
done
exit $RETURN

40
tests/scripts/travis_setup.sh

@ -0,0 +1,40 @@
#!/bin/bash
mysql -u root -e 'create database drupal;'
mysql -u root -e "create database fedora;"
mysql -u root -e "GRANT ALL PRIVILEGES ON fedora.* To 'fedora'@'localhost' IDENTIFIED BY 'fedora';"
mysql -u root -e "GRANT ALL PRIVILEGES ON drupal.* To 'drupal'@'localhost' IDENTIFIED BY 'drupal';"
cd $HOME
git clone git://github.com/Islandora/tuque.git
git clone -b $FEDORA_VERSION git://github.com/Islandora/islandora_tomcat.git
cd islandora_tomcat
export CATALINA_HOME='.'
./bin/startup.sh
cd $HOME
pear upgrade –force Console_Getopt
pear upgrade –force pear
pear upgrade-all
pear channel-discover pear.drush.org
pear channel-discover pear.drush.org
pear channel-discover pear.phpqatools.org
pear channel-discover pear.netpirates.net
pear install pear/PHP_CodeSniffer
pear install pear.phpunit.de/phpcpd
pear install drush/drush
phpenv rehash
drush dl --yes drupal
cd drupal-*
drush si standard --db-url=mysql://drupal:drupal@localhost/drupal --yes
drush runserver --php-cgi=$HOME/.phpenv/shims/php-cgi localhost:8081 &>/dev/null &
ln -s $ISLANDORA_DIR sites/all/modules/islandora
mv sites/all/modules/islandora/tests/travis.test_config.ini sites/all/modules/islandora/tests/test_config.ini
mkdir sites/all/libraries
ln -s $HOME/tuque sites/all/libraries/tuque
drush dl --yes coder
drush dl --yes potx
drush en --yes coder_review
drush en --yes simpletest
drush en --yes potx
drush en --user=1 --yes islandora
drush cc all
sleep 20

6
tests/travis.test_config.ini

@ -0,0 +1,6 @@
[fedora]
fedora_url = "http://localhost:8080/fedora"
use_drupal_filter = TRUE
drupal_filter_file = "/home/travis/islandora_tomcat/fedora/server/config/filter-drupal.xml"
admin_user = "fedoraAdmin"
admin_pass = "fedoraAdmin"

17
theme/islandora-objects-grid.tpl.php

@ -0,0 +1,17 @@
<?php
/**
* @file
* Render a bunch of objects in a list or grid view.
*/
?>
<div class="islandora-objects-grid clearfix">
<?php foreach($objects as $object): ?>
<div class="islandora-objects-grid-item clearfix">
<dl class="islandora-object <?php print $object['class']; ?>">
<dt class="islandora-object-thumb"><?php print $object['thumb']; ?></dt>
<dd class="islandora-object-caption"><?php print $object['link']; ?></dd>
</dl>
</div>
<?php endforeach; ?>
</div>

29
theme/islandora-objects-list.tpl.php

@ -0,0 +1,29 @@
<?php
/**
* @file
* Render a bunch of objects in a list or grid view.
*/
?>
<div class="islandora-objects-list">
<?php $row_field = 0; ?>
<?php foreach($objects as $object): ?>
<?php $first = ($row_field == 0) ? 'first' : ''; ?>
<div class="islandora-objects-list-item clearfix">
<dl class="islandora-object <?php print $object['class']; ?>">
<dt class="islandora-object-thumb">
<?php print $object['thumb']; ?>
</dt>
<dd class="islandora-object-caption <?php print $object['class']?> <?php print $first; ?>">
<strong>
<?php print $object['link']; ?>
</strong>
</dd>
<dd class="islandora-object-description">
<?php print $object['description']; ?>
</dd>
</dl>
</div>
<?php $row_field++; ?>
<?php endforeach; ?>
</div>

21
theme/islandora-objects.tpl.php

@ -0,0 +1,21 @@
<?php
/**
* @file
* Render a bunch of objects in a list or grid view.
*/
?>
<div class="islandora-objects clearfix">
<span class="islandora-objects-display-switch">
<?php
print theme('links', array(
'links' => $display_links,
'attributes' => array('class' => array('links', 'inline')),
)
);
?>
</span>
<?php print $pager; ?>
<?php print $content; ?>
<?php print $pager; ?>
</div>

161
theme/theme.inc

@ -29,7 +29,9 @@ function islandora_preprocess_islandora_default_edit(array &$variables) {
$rows[] = array(
array(
'class' => 'datastream-id',
'data' => l($ds->id, islandora_datastream_get_url($ds, 'view')),
'data' => theme('islandora_datastream_view_link', array(
'datastream' => $ds,
)),
),
array(
'class' => 'datastream-label',
@ -49,15 +51,21 @@ function islandora_preprocess_islandora_default_edit(array &$variables) {
),
array(
'class' => 'datastream-download',
'data' => l(t('download'), islandora_datastream_get_url($ds, 'download')),
'data' => theme('islandora_datastream_download_link', array(
'datastream' => $ds,
)),
),
array(
'class' => 'datstream-edit',
'data' => islandora_datastream_edit_get_link($ds),
'data' => theme('islandora_datastream_edit_link', array(
'datastream' => $ds,
)),
),
array(
'class' => 'datastream-delete',
'data' => islandora_datastream_get_delete_link($ds),
'data' => theme('islandora_datastream_delete_link', array(
'datastream' => $ds,
)),
),
);
}
@ -95,7 +103,9 @@ function islandora_preprocess_islandora_default(&$variables) {
$download_path = islandora_datastream_get_url($ds, 'download');
$datastreams[$id]['id'] = $id;
$datastreams[$id]['label'] = $label;
$datastreams[$id]['label_link'] = l($label, $download_path);
$datastreams[$id]['label_link'] = islandora_datastream_access(FEDORA_VIEW_OBJECTS, $ds) ?
l($label, $download_path) :
$label;
$datastreams[$id]['download_url'] = $download_path;
$datastreams[$id]['mimetype'] = $ds->mimetype;
$datastreams[$id]['size'] = islandora_datastream_get_human_readable_size($ds);
@ -108,14 +118,14 @@ function islandora_preprocess_islandora_default(&$variables) {
}
$variables['datastreams'] = $datastreams;
// Objects in fcrepo4 don't always contain a DC datastream.
if (isset($islandora_object['DC'])) {
if (isset($islandora_object['DC']) && islandora_datastream_access(FEDORA_VIEW_OBJECTS, $islandora_object['DC'])) {
$dc_object = DublinCore::importFromXMLString($islandora_object['DC']->content);
$dc_array = $dc_object->asArray();
}
$variables['dc_array'] = isset($dc_array) ? $dc_array : array();
$variables['islandora_dublin_core'] = isset($dc_object) ? $dc_object : NULL;
$variables['islandora_object_label'] = $islandora_object->label;
if (isset($islandora_object['TN'])) {
if (isset($islandora_object['TN']) && islandora_datastream_access(FEDORA_VIEW_OBJECTS, $islandora_object['TN'])) {
$variables['islandora_thumbnail_url'] = url("islandora/object/{$islandora_object->id}/datastream/TN/view");
}
}
@ -157,3 +167,140 @@ function islandora_preprocess_islandora_object_print(array &$variables) {
function theme_islandora_object_print(array &$variables) {
return drupal_render($variables['content']);
}
/**
* Implements hook_preprocess_theme().
*/
function islandora_preprocess_islandora_objects(array &$variables) {
module_load_include('inc', 'islandora_paged_content', 'includes/utilities');
$display = (empty($_GET['display'])) ? 'grid' : $_GET['display'];
$grid_display = $display == 'grid';
$list_display = !$grid_display;
$query_params = drupal_get_query_parameters($_GET);
$variables['display_links'] = array(
array(
'title' => t('Grid view'),
'href' => url($_GET['q'], array('absolute' => TRUE)),
'attributes' => array(
'class' => $grid_display ? 'active' : '',
),
'query' => array('display' => 'grid') + $query_params,
),
array(
'title' => t('List view'),
'href' => url($_GET['q'], array('absolute' => TRUE)),
'attributes' => array(
'class' => $list_display ? 'active' : '',
),
'query' => array('display' => 'list') + $query_params,
),
);
// Pager.
$objects = $variables['objects'];
$limit = $variables['limit'];
$page_size = $variables['page_size'];
$page = pager_default_initialize(count($objects), $limit);
$objects = array_slice($objects, $page * $limit, $limit);
$variables['pager'] = theme('pager', array('quantity' => 10));
// Content.
$map_objects = function($o) {
$o = islandora_object_load($o);
$url = "islandora/object/{$o->id}";
$link_options = array('html' => TRUE, 'attributes' => array('title' => $o->label));
$img = islandora_datastream_access(FEDORA_VIEW_OBJECTS, $o['TN']) ?
theme('image', array('path' => url("$url/datastream/TN/view"), 'attributes' => array())) :
'';
$description = NULL;
if (isset($o['DC']) && islandora_datastream_access(FEDORA_VIEW_OBJECTS, $o['DC'])) {
$dc = DublinCore::importFromXMLString($o['DC']->content);
if ($dc) {
$dc = $dc->asArray();
$description = $dc['dc:description']['value'];
}
}
return array(
'label' => $o->label,
'class' => drupal_strtolower(preg_replace('/[^A-Za-z0-9]/', '-', $o->id)),
'link' => l($o->label, $url, $link_options),
'thumb' => l($img, $url, $link_options),
'description' => $description,
);
};
$objects = array_map($map_objects, $objects);
$theme = $grid_display ? 'islandora_objects_grid' : 'islandora_objects_list';
$variables['content'] = theme($theme, array('objects' => $objects));
$module_path = drupal_get_path('module', 'islandora');
drupal_add_css("$module_path/css/islandora.objects.css");
}
/**
* Renders a link to allow downloading of a datatream.
*
* @param array $vars
* An array containing:
* - datastream: An AbstractDatastream for which to generate a download link.
*/
function theme_islandora_datastream_download_link(array $vars) {
$datastream = $vars['datastream'];
module_load_include('inc', 'islandora', 'includes/utilities');
$label = t('download');
return islandora_datastream_access(FEDORA_VIEW_OBJECTS, $datastream) ?
l($label, islandora_datastream_get_url($datastream, 'download')) :
'';
}
/**
* Renders a link to allow viewing of a datatream.
*
* @param array $vars
* An array containing:
* - datastream: An AbstractDatastream for which to generate a view link.
*/
function theme_islandora_datastream_view_link(array $vars) {
$datastream = $vars['datastream'];
module_load_include('inc', 'islandora', 'includes/utilities');
$label = check_plain($datastream->id);
return islandora_datastream_access(FEDORA_VIEW_OBJECTS, $datastream) ?
l($label, islandora_datastream_get_url($datastream, 'view')) :
$label;
}
/**
* Renders a link to allow deleting of a datatream.
*
* @param array $vars
* An array containing:
* - datastream: An AbstractDatastream for which to generate a delete link.
*/
function theme_islandora_datastream_delete_link(array $vars) {
$datastream = $vars['datastream'];
$datastreams = module_invoke_all('islandora_undeletable_datastreams', $datastream->parent->models);
$can_delete = !in_array($datastream->id, $datastreams) && islandora_datastream_access(FEDORA_PURGE, $datastream);
return $can_delete ?
l(t('delete'), "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/delete") :
'';
}
/**
* Renders a link to allow editing of a datatream.
*
* @param array $vars
* An array containing:
* - datastream: An AbstractDatastream for which to generate a edit link.
*/
function theme_islandora_datastream_edit_link(array $vars) {
$datastream = $vars['datastream'];
$edit_registry = module_invoke_all('islandora_edit_datastream_registry', $datastream->parent, $datastream);
$can_edit = count($edit_registry) > 0 && islandora_datastream_access(FEDORA_METADATA_EDIT, $datastream);
return $can_edit ?
l(t('edit'), "islandora/object/{$datastream->parent->id}/datastream/{$datastream->id}/edit") :
'';
}

Loading…
Cancel
Save