Browse Source

Merge pull request #243 from nigelgbanks/7.x-tuque-wrapper

Created hooks and implemented them as part of the tuque wrapper classes.
pull/249/head
Jonathan Green 12 years ago
parent
commit
e5ae847022
  1. 1
      .gitignore
  2. 78
      includes/IslandoraTuqueWrapper.inc
  3. 1
      includes/islandora_tuque.inc
  4. 360
      includes/islandora_tuque_wrapper.inc
  5. 64
      includes/utilities.inc
  6. 311
      islandora.api.php
  7. 5
      islandora.info
  8. 197
      islandora.module
  9. 3
      tests/README
  10. 6
      tests/default.test_config.ini
  11. 48
      tests/islandora_authtokens.test
  12. 213
      tests/islandora_hooks.test
  13. 7
      tests/islandora_hooks_test.info
  14. 152
      tests/islandora_hooks_test.module
  15. 108
      tests/islandora_web_test_case.inc
  16. 4
      tests/test_config.ini

1
.gitignore vendored

@ -1,2 +1,3 @@
cache.properties
.DS_Store
tests/test_config.ini

78
includes/IslandoraTuqueWrapper.inc

@ -1,78 +0,0 @@
<?php
/**
* @file
*
* Wrapper around the tuque library, allows for autoloading of Islandora Tuque
* Objects.
*
* @todo Overload functions and apply pre/post hooks.
*/
$islandora_module_path = drupal_get_path('module', 'islandora');
//do this until we expost these in a module or library
@include_once 'sites/all/libraries/tuque/Datastream.php';
@include_once 'sites/all/libraries/tuque/FedoraApi.php';
@include_once 'sites/all/libraries/tuque/FedoraApiSerializer.php';
@include_once 'sites/all/libraries/tuque/Object.php';
@include_once 'sites/all/libraries/tuque/RepositoryConnection.php';
@include_once 'sites/all/libraries/tuque/Cache.php';
@include_once 'sites/all/libraries/tuque/RepositoryException.php';
@include_once 'sites/all/libraries/tuque/Repository.php';
@include_once 'sites/all/libraries/tuque/FedoraRelationships.php';
@include_once "$islandora_module_path/libraries/tuque/Datastream.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraApi.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraApiSerializer.php";
@include_once "$islandora_module_path/libraries/tuque/Object.php";
@include_once "$islandora_module_path/libraries/tuque/RepositoryConnection.php";
@include_once "$islandora_module_path/libraries/tuque/Cache.php";
@include_once "$islandora_module_path/libraries/tuque/RepositoryException.php";
@include_once "$islandora_module_path/libraries/tuque/Repository.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraRelationships.php";
class IslandoraFedoraRepository extends FedoraRepository {
protected $queryClass = 'IslandoraRepositoryQuery';
protected $newObjectClass = 'IslandoraNewFedoraObject';
protected $objectClass = 'IslandoraFedoraObject';
}
class IslandoraRepositoryQuery extends RepositoryQuery {}
class IslandoraNewFedoraObject extends NewFedoraObject {
protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream';
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
}
class IslandoraFedoraObject extends FedoraObject {
protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream';
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
}
class IslandoraRepositoryConnection extends RepositoryConnection {}
class IslandoraFedoraApi extends FedoraApi {}
class IslandoraSimpleCache extends SimpleCache {}
class IslandoraNewFedoraDatastream extends NewFedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraDatastream extends FedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraRelsExt extends FedoraRelsExt {}
class IslandoraFedoraRelsInt extends FedoraRelsInt {}

1
includes/IslandoraTuque.inc → includes/islandora_tuque.inc

@ -78,7 +78,6 @@ class IslandoraTuque {
}
if (self::exists()) {
module_load_include('inc', 'islandora', 'includes/IslandoraTuqueWrapper');
$this->connection = new IslandoraRepositoryConnection($url, $user_string, $pass_string);
$this->connection->reuseConnection = TRUE;
$this->api = new IslandoraFedoraApi($this->connection);

360
includes/islandora_tuque_wrapper.inc

@ -0,0 +1,360 @@
<?php
/**
* @file
* Wrapper around the tuque library, allows for autoloading of Islandora Tuque
* Objects.
*
* @todo Overload functions and apply pre/post hooks.
*/
$islandora_module_path = drupal_get_path('module', 'islandora');
// @todo this until we expost these in a module or library
@include_once 'sites/all/libraries/tuque/Datastream.php';
@include_once 'sites/all/libraries/tuque/FedoraApi.php';
@include_once 'sites/all/libraries/tuque/FedoraApiSerializer.php';
@include_once 'sites/all/libraries/tuque/Object.php';
@include_once 'sites/all/libraries/tuque/RepositoryConnection.php';
@include_once 'sites/all/libraries/tuque/Cache.php';
@include_once 'sites/all/libraries/tuque/RepositoryException.php';
@include_once 'sites/all/libraries/tuque/Repository.php';
@include_once 'sites/all/libraries/tuque/FedoraRelationships.php';
@include_once "$islandora_module_path/libraries/tuque/Datastream.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraApi.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraApiSerializer.php";
@include_once "$islandora_module_path/libraries/tuque/Object.php";
@include_once "$islandora_module_path/libraries/tuque/RepositoryConnection.php";
@include_once "$islandora_module_path/libraries/tuque/Cache.php";
@include_once "$islandora_module_path/libraries/tuque/RepositoryException.php";
@include_once "$islandora_module_path/libraries/tuque/Repository.php";
@include_once "$islandora_module_path/libraries/tuque/FedoraRelationships.php";
/**
* 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);
}
/**
* 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');
foreach ($object->models as $model) {
$types[] = "{$model}_{$datastream->id}_islandora_datastream";
}
drupal_alter($types, $object, $datastream, $context);
}
/**
* Constructs a list of hooks from the given paramenters and invokes them.
*/
function islandora_invoke_object_hooks($hook, array $models) {
module_load_include('inc', 'islandora', 'includes/utilities');
return islandora_invoke_hook_list($hook, $models, array_slice(func_get_args(), 2));
}
/**
* Constructs a list of hooks from the given paramenters and invokes them.
*/
function islandora_invoke_datastream_hooks($hook, array $models, $dsid) {
module_load_include('inc', 'islandora', 'includes/utilities');
$refinements = array();
foreach ($models as $model) {
$refinements[] = "{$model}_{$dsid}";
}
return islandora_invoke_hook_list($hook, $refinements, array_slice(func_get_args(), 3));
}
class IslandoraFedoraRepository extends FedoraRepository {
protected $queryClass = 'IslandoraRepositoryQuery';
protected $newObjectClass = 'IslandoraNewFedoraObject';
protected $objectClass = 'IslandoraFedoraObject';
/**
* Ingest the given object.
*
* @see FedoraRepository::ingestObject()
*/
public function ingestObject(NewFedoraObject &$object) {
$context = array(
'action' => 'ingest',
'block' => FALSE,
);
islandora_alter_object($object, $context);
try {
if ($context['block']) {
throw new Exception('Ingest Object was blocked.');
}
$ret = parent::ingestObject($object);
islandora_invoke_object_hooks(ISLANDORA_OBJECT_INGESTED_HOOK, $object->models, $object);
// Call the ingested datastream hooks for NewFedoraObject's after the
// object had been ingested.
foreach ($object as $dsid => $datastream) {
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_INGESTED_HOOK, $object->models, $dsid, $object, $datastream);
}
return $ret;
}
catch (Exception $e) {
watchdog('islandora', 'Failed to ingest object: @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $object->id,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
throw $e;
}
}
}
class IslandoraRepositoryQuery extends RepositoryQuery {}
class IslandoraNewFedoraObject extends NewFedoraObject {
protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream';
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
}
class IslandoraFedoraObject extends FedoraObject {
protected $newFedoraDatastreamClass = 'IslandoraNewFedoraDatastream';
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
/**
* Ingest the given datastream.
*
* @see FedoraObject::ingestDatastream()
*/
public function ingestDatastream(&$datastream) {
$object = $datastream->parent;
$context = array(
'action' => 'ingest',
'block' => FALSE,
);
islandora_alter_datastream($object, $datastream, $context);
try {
if ($context['block']) {
throw new Exception('Ingest Datastream was blocked.');
}
$ret = parent::ingestDatastream($datastream);
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_INGESTED_HOOK, $object->models, $datastream->id, $object, $datastream);
return $ret;
}
catch (Exception $e) {
watchdog('islandora', 'Failed to ingest object: @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $object->id,
'@dsid' => $datastream->id,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
throw $e;
}
}
}
class IslandoraRepositoryConnection extends RepositoryConnection {}
class IslandoraFedoraApi extends FedoraApi {
/**
* Instantiate a IslandoraFedoraApi object.
*
* @see FedoraApi::__construct()
*/
public function __construct(IslandoraRepositoryConnection $connection, FedoraApiSerializer $serializer = NULL) {
if (!$serializer) {
$serializer = new FedoraApiSerializer();
}
$this->a = new FedoraApiA($connection, $serializer);
$this->m = new IslandoraFedoraApiM($connection, $serializer);
$this->connection = $connection;
}
}
class IslandoraFedoraApiM extends FedoraApiM {
/**
* Update a datastream.
*
* Either changing its metadata, updaing the datastream contents or both.
*
* @throws Exception
* If the modify datastream request was block by some module.
*
* @see FedoraApiM::modifyDatastream
*/
public function modifyDatastream($pid, $dsid, $params = array()) {
$object = islandora_object_load($pid);
$datastream = $object[$dsid];
$context = array(
'action' => 'modify',
'block' => FALSE,
'params' => $params,
);
islandora_alter_datastream($object, $datastream, $context);
try {
if ($context['block']) {
throw new Exception('Modify Datastream was blocked.');
}
$ret = parent::modifyDatastream($pid, $dsid, $params);
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_MODIFIED_HOOK, $object->models, $dsid, $object, $datastream);
if (isset($params['dsState']) && $params['dsState'] == 'D') {
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_PURGED_HOOK, $object->models, $dsid, $object, $dsid);
}
return $ret;
}
catch(Exception $e) {
watchdog('islandora', 'Failed to modify datastream @dsid from @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@dsid' => $dsid,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
throw $e;
}
}
/**
* Update Fedora Object parameters.
*
* @see FedoraApiM::modifyObject
*/
public function modifyObject($pid, $params = NULL) {
$object = islandora_object_load($pid);
$context = array(
'action' => 'modify',
'block' => FALSE,
'params' => $params,
);
islandora_alter_object($object, $context);
try {
if ($context['block']) {
throw new Exception('Modify Object was blocked.');
}
$ret = parent::modifyObject($pid, $params);
islandora_invoke_object_hooks(ISLANDORA_OBJECT_MODIFIED_HOOK, $object->models, $object);
if (isset($params['state']) && $params['state'] == 'D') {
islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $object->models, $object->id);
}
return $ret;
}
catch(Exception $e) {
watchdog('islandora', 'Failed to modify object: @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
throw $e;
}
}
/**
* Purge a datastream from from Fedora.
*
* @see FedoraApiM::purgeDatastream
*/
public function purgeDatastream($pid, $dsid, $params = array()) {
$object = islandora_object_load($pid);
$context = array(
'action' => 'purge',
'purge' => TRUE,
'delete' => FALSE,
'block' => FALSE,
);
islandora_alter_datastream($object, $object[$dsid], $context);
try {
$action = $context['block'] ? 'block' : FALSE;
$action = (!$action && $context['delete']) ? 'delete' : $action;
$action = !$action ? 'purge' : $action;
switch ($action) {
case 'block':
throw new Exception('Purge Datastream was blocked.');
break;
case 'delete':
$object[$dsid]->state = 'D';
return array();
default:
$ret = parent::purgeDatastream($pid, $dsid, $params);
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_PURGED_HOOK, $object->models, $dsid, $object, $dsid);
return $ret;
}
}
catch(Exception $e) {
watchdog('islandora', 'Failed to purge datastream @dsid from @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@dsid' => $dsid,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
throw $e;
}
}
/**
* Purge an object.
*
* @see FedoraApiM::purgeObject
*/
public function purgeObject($pid, $log_message = NULL) {
$object = islandora_object_load($pid);
$context = array(
'action' => 'purge',
'purge' => TRUE,
'delete' => FALSE,
'block' => FALSE,
);
islandora_alter_object($object, $context);
try {
$action = $context['block'] ? 'block' : FALSE;
$action = (!$action && $context['delete']) ? 'delete' : $action;
$action = !$action ? 'purge' : $action;
$models = $object->models;
switch ($action) {
case 'block':
throw new Exception('Purge object was blocked.');
break;
case 'delete':
$object->state = 'D';
return '';
default:
$ret = parent::purgeObject($pid, $log_message);
islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $models, $pid);
return $ret;
}
}
catch(Exception $e) {
watchdog('islandora', 'Failed to purge object @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $pid,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
throw $e;
}
}
}
class IslandoraSimpleCache extends SimpleCache {}
class IslandoraNewFedoraDatastream extends NewFedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraDatastream extends FedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
}
class IslandoraFedoraRelsExt extends FedoraRelsExt {}
class IslandoraFedoraRelsInt extends FedoraRelsInt {}

64
includes/utilities.inc

@ -112,29 +112,65 @@ function islandora_describe_repository($url = NULL) {
}
/**
* Build a list of all the hooks to call.
* Build and invoke a list of hooks by combining the given hook and refinements.
*
* The given hook will be called as MODULE_HOOK, and for each hook refinement
* as MODULE_REFINEMENT_HOOK. Any additional arguments passed to this function
* will be passed as arguments to module_invoke_all().
*
* Concatenates the each pid (escaped) to the hook name, for calling in
* module_invoke_all().
* @see islandora_build_hook_list()
* To see how the hook list is generated.
*
* @param string $hook
* A hook to call.
* @param array $pids
* An array of PIDs (probably content models).
* @param array $refinements
* An array of strings, that will be escaped and concatinated with the given
* hook. This will most likely be PIDs/DSIDs/Labels etc. We often refine our
* hooks using an objects model.
* @param array $args
* Any arguments to pass onto module_invoke_all().
*
* @return array
* An array with each PID escaped and concatenated with the base hook name,
* in addition to the base hook name at the end.
* The merged results from all the hooks.
*/
function islandora_build_hook_list($hook, $pids = array()) {
$hooks = array();
$pids = array_unique($pids);
foreach ($pids as $pid) {
$hooks[] = islandora_escape_pid_for_function($pid) . '_' . $hook;
function islandora_invoke_hook_list($hook, array $refinements, array $args) {
$return = array();
foreach (islandora_build_hook_list($hook, $refinements) as $hook) {
array_unshift($args, $hook);
$result = call_user_func_array('module_invoke_all', $args);
$return = array_merge_recursive($return, $result);
array_shift($args);
}
return $return;
}
$hooks[] = $hook;
/**
* Build a list of all the hooks to call.
*
* Concatenates each hook $refinement (escaped) to the hook name, for calling
* with module_invoke_all().
*
* Any non-valid PHP function characters in the given refinements are
* converted to "_" characters.
*
* @param string $hook
* The base hook to concatenate.
* @param array $refinements
* An array of strings, that will be escaped and concatinated with the given
* hook. This will most likely be PIDs/DSIDs/Labels etc. We often refine our
* hooks using an objects model.
*
* @return array
* An array with each refinement escaped and concatenated with the base hook
* name, in addition to the base hook name.
*/
function islandora_build_hook_list($hook, $refinements = array()) {
$refinements = array_unique($refinements);
$hooks = array($hook);
foreach ($refinements as $refinement) {
$refinement = preg_replace('/[^a-zA-Z0-9_]/', '_', $refinement);
$hooks[] = "{$refinement}_{$hook}";
}
return $hooks;
}

311
islandora.api.php

@ -2,24 +2,26 @@
/**
* @file
* This file lists and documents all available hook functions to manipulate data.
* This file documents all available hook functions to manipulate data.
*/
/**
* Generate a repository objects view.
*
* @param FedoraObject $fedora_object
* A Tuque FedoraObject being operated on.
* @param FedoraObject $object
* The object to display
* @param object $user
* The user accessing the object.
* @param string $page_number
* The page in the content.
* @param string $page_size: The size of the page.
* @param string $page_size
* The size of the page.
*
* @return array
* An array whose values are markup.
*/
function hook_islandora_view_object($fedora_object, $user, $page_number, $page_size) {}
function hook_islandora_view_object($object, $user, $page_number, $page_size) {
}
/**
* Generate an object's display for the given content model.
@ -27,35 +29,38 @@ function hook_islandora_view_object($fedora_object, $user, $page_number, $page_s
* Content models PIDs have colons and hyphens changed to underscores, to
* create the hook name.
*
* @param type $fedora_object
* @param FedoraObject $object
* A Tuque FedoraObject
*
* @return array
* An array whose values are markup.
*/
function hook_CMODEL_PID_islandora_view_object($fedora_object) {}
function hook_CMODEL_PID_islandora_view_object($object) {
}
/**
* Alter display output after it has been generated.
*
* @param FedoraObject $fedora_object
* @param FedoraObject $object
* A Tuque FedoraObject being operated on.
* @param array $arr
* @param array $rendered
* An arr of rendered views.
*/
function hook_islandora_view_object_alter(&$fedora_object, &$arr) {}
function hook_islandora_view_object_alter(&$object, &$rendered) {
}
/**
* Generate an object's management display.
*
* @param type $fedora_object
* @param FedoraObject $object
* A Tuque FedoraObject
*
* @return array
* An array whose values are markup.
*/
function hook_islandora_edit_object($fedora_object) {}
function hook_islandora_edit_object($object) {
}
/**
* Generate an object's management display for the given content model.
@ -63,148 +68,282 @@ function hook_islandora_edit_object($fedora_object) {}
* Content models PIDs have colons and hyphens changed to underscores, to
* create the hook name.
*
* @param type $fedora_object
* @param FedoraObject $object
* A Tuque FedoraObject
*
* @return array
* An array whose values are markup.
*/
function hook_CMODEL_PID_islandora_edit_object($fedora_object) {}
function hook_CMODEL_PID_islandora_edit_object($object) {
}
/**
* Allow management display output to be altered.
*
* @param type $fedora_object
* @param FedoraObject $object
* A Tuque FedoraObject
* @param type $arr
* @param array $rendered
* an arr of rendered views
*/
function hook_islandora_edit_object_alter(&$fedora_object, &$arr) {}
function hook_islandora_edit_object_alter(&$object, &$rendered) {
}
/**
* Allows modules to alter the object or block/modify the given action.
*
* This alter hook will be called before any object is ingested, modified or
* purged.
*
* Changing object properties such as "label", or "state", are considered
* modifications, where as manipulating an object's datstreams are not.
*
* @param AbstractFedoraObject $object
* The object to alter.
* @param array $context
* An associative array containing:
* - action: A string either 'ingest', 'purge', 'modify'.
* - block: Either TRUE or FALSE, if TRUE the action won't take place.
* Defaults to FALSE.
* - purge: Either TRUE or FALSE, only present when the action is 'purge'.
* If 'delete' or 'block' is set to TRUE, they will take precedence.
* Defaults to TRUE.
* - delete: Either TRUE or FALSE, only present when the action is 'purge'.
* If TRUE it will cause the object's state to be set to 'D' instead.
* If 'block' is set to TRUE, it will take precedence.
* Defaults to FALSE,
* - params: An associative array, only present when the action is 'modify'.
* The key value pairs repersent what values will be changed. The params
* will match the same params as passed to FedoraApiM::modifyObject().
*
* @see FedoraApiM::modifyObject()
*/
function hook_islandora_object_alter(AbstractFedoraObject $object, array &$context) {
}
/**
* Allows modules to add to an objects ingest process.
* Allows modules to alter the object or block/modify the given action.
*
* @param FedoraObject $fedora_object
* A Tuque FedoraObject.
* @see hook_islandora_object_alter()
*/
function hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context) {
}
/**
* Allows modules to alter the datastream or block/modify the given action.
*
* This alter hook will be called before any datastream is ingested, modified or
* purged.
*
* Adding datastreams to NewFedoraObject's will not trigger this alter hook
* 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
* at all.
*
* Changing datastream's properties such as "label", or "state", are considered
* modifications, as well as changing the datastreams content.
*
* @param AbstractFedoraObject $object
* The object to the datastream belong to.
* @param AbstractFedoraDatastream $datastream
* The datastream to alter.
* @param array $context
* An associative array containing:
* - action: A string either 'ingest', 'purge', 'modify'.
* - block: Either TRUE or FALSE, if TRUE the action won't take place.
* Defaults to FALSE.
* - purge: Either TRUE or FALSE, only present when the action is 'purge'.
* If 'delete' or 'block' is set to TRUE, they will take precedence.
* Defaults to TRUE.
* - delete: Either TRUE or FALSE, only present when the action is 'purge'.
* If TRUE it will cause the object's state to be set to 'D' instead.
* If 'block' is set to TRUE, it will take precedence.
* Defaults to FALSE,
* - params: An associative array, only present when the action is 'modify'.
* The key value pairs repersent what values will be changed. The params
* will match the same params as passed to FedoraApiM::modifyDatastream().
*
* @see FedoraApiM::modifyDatastream()
*/
function hook_islandora_ingest_post_ingest($fedora_object) {}
function hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) {
}
/**
* Allow modules to add to the ingest process of a specific content model.
* Allows modules to alter the datastream or block/modify the given action.
*
* @see hook_islandora_datastream_alter()
*/
function hook_CMODEL_PID_islandora_ingest_post_ingest($fedora_object) {}
function hook_CMODEL_PID_DSID_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) {
}
/**
* Allows modules to add to a repository objects view/edit(/misc) process.
* Notify modules that the given object was ingested.
*
* If you implement this hook you must also register your module with
* hook_islandora_hook_info().
* This hook is called after an object has been successfully ingested via a
* FedoraRepository object.
*
* @param FedoraObject $fedora_object
* A Tuque FedoraObject.
* @note
* 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.
*
* @return array|null
* An associative array with 'deleted' mapped to TRUE--indicating that the
* object should just be marked as deleted, instead of actually being
* purged--or NULL/no return if we just need to do something before the
* is purged.
* @param FedoraObject $object
* The object that was ingested.
*/
function hook_islandora_pre_purge_object($fedora_object) {}
function hook_islandora_object_ingested(FedoraObject $object) {
}
/**
* Allow modules to react to the purge process of a specific content model.
* Notify modules that the given object was ingested.
*
* @see hook_islandora_pre_purge_object()
* @see hook_islandora_object_ingested()
*/
function hook_CMODEL_PID_islandora_pre_purge_object($fedora_object) {}
function hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object) {
}
/**
* Register potential ingest routes.
* Notify modules that the given object was modified.
*
* Implementations should return an array containing possible routes.
* This hook is called after an object has been successfully modified.
*
* Changing object properties such as "label", or "state", are considered
* modifications, where as manipulating an object's datstreams are not.
*
* @param FedoraObject $object
* The object that was ingested.
*
* @todo We should also include what changes were made in a additional
* parameter.
*/
function hook_islandora_ingest_registry($collection_object) {
$reg = array(
array(
'name' => t('Ingest route name'),
'url' => 'ingest_route/url',
'weight' => 0,
),
);
return $reg;
function hook_islandora_object_modified(FedoraObject $object) {
}
/**
* Register a datastream edit route/form.
* Notify modules that the given object was ingested.
*
* @param $islandora_object
* @param $ds_id
* @see hook_islandora_object_modified()
*/
function hook_islandora_edit_datastream_registry($islandora_object, $ds_id) {}
function hook_CMODEL_PID_islandora_object_modified(FedoraObject $object) {
}
/**
* Alter an object before it gets used further down the stack.
* Notify modules that the given object was purged/deleted.
*
* @param type $object
* A Tuque FedoraObject
* This hook is called after an object has been successfully purged, or
* when its state has been changed to "Deleted".
*
* @param string $pid
* The ID of the object that was purged/deleted.
*/
function hook_islandora_object_alter($fedora_object) {}
function hook_islandora_object_purged($pid) {
}
/**
* Allow modification of an object before ingesting.
* Notify modules that the given object was purged/deleted.
*
* @param type $islandora_object
* A Tuque FedoraObject
* @see hook_islandora_object_purged()
*/
function hook_CMODEL_PID_islandora_object_purged($pid) {
}
/**
* Notify modules that the given datastream was ingested.
*
* This hook is called after the datastream has been successfully ingested.
*
* @note
* 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
* The object the datastream belongs to.
* @param FedoraDatastream $datastream
* The ingested datastream.
*/
function hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) {
}
/**
* Notify modules that the given datastream was ingested.
*
* @see hook_islandora_object_ingested()
*/
function hook_islandora_ingest_pre_ingest($islandora_object) {}
function hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) {
}
/**
* Allow modification of objects of a certain content model before ingesting.
* Notify modules that the given datastream was modified.
*
* @see hook_islandora_ingest_pre_ingest()
* This hook is called after an datastream has been successfully modified.
*
* Changing datastream properties such as "label", or "state", are considered
* modifications, as well as the datastreams content.
*
* @param FedoraObject $object
* The object the datastream belongs to.
* @param FedoraDatastream $datastream
* The datastream that was ingested.
*
* @todo We should also include what changes were made in a additional
* parameter.
*/
function hook_CMODEL_PID_islandora_ingest_pre_ingest($islandora_object) {}
function hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) {
}
/**
* Allow modules to setup for the purge of a datastream.
* Notify modules that the given datastream was ingested.
*
* @param object $datastream
* A Tuque FedoraDatastream object.
* @see hook_islandora_datastream_modified()
*/
function hook_islandora_pre_purge_datastream($datastream) {}
function hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) {
}
/**
* Allow modules to react after a datastream is purged.
* Notify modules that the given datastream was purged/deleted.
*
* This hook is called after an datastream has been successfully purged, or
* when its state has been changed to "Deleted".
*
* @param object $object
* A Tuque FedoraObject.
* @param FedoraObject $object
* The object the datastream belonged to.
* @param string $dsid
* A id of the former datastream.
* The ID of the datastream that was purged/deleted.
*/
function hook_islandora_datastream_purged(FedoraObject $object, $dsid) {
}
/**
* Notify modules that the given datastream was purged/deleted.
*
* @see hook_islandora_datastream_purged()
*/
function hook_islandora_post_purge_datastream($object, $dsid) {}
function hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid) {
}
/**
* Allow modules to react post-purge.
* Register a datastream edit route/form.
*
* @param string $object_id
* The former object's PID.
* @param array $content_models
* An array containing the models to which the former object.
* @param FedoraObject $object
* The object to check.
* @param string $dsid
* todo
*/
function hook_islandora_post_purge_object($object_id, $content_models) {}
function hook_islandora_edit_datastream_registry($object, $dsid) {
}
/**
* Registry hook for required objects.
*
* Solution packs can include data to create certain objects that describe or
* help the objects it would create. This includes collection objects and content
* models.
* help the objects it would create. This includes collection objects and
* content models.
*
* @see islandora_solution_packs_admin()
* @see islandora_install_solution_pack()
* @example islandora_islandora_required_objects()
*/
function hook_islandora_required_objects() {}
function hook_islandora_required_objects() {
}
/**
* Registry hook for viewers that can be implemented by solution packs.
@ -215,13 +354,14 @@ function hook_islandora_required_objects() {}
* @see islandora_get_viewers()
* @see islandora_get_viewer_callback()
*/
function hook_islandora_viewer_info() {}
function hook_islandora_viewer_info() {
}
/**
* Returns a list of datastreams that are determined to be undeletable.
*/
function hook_islandora_undeletable_datastreams(array $models) {}
function hook_islandora_undeletable_datastreams(array $models) {
}
/**
* Define steps used in the islandora_ingest_form() ingest process.
@ -265,4 +405,5 @@ function hook_islandora_ingest_steps(array $form_state) {
*
* @see hook_islandora_ingest_steps()
*/
function hook_CMODEL_PID_islandora_ingest_steps(array $form_state) {}
function hook_CMODEL_PID_islandora_ingest_steps(array $form_state) {
}

5
islandora.info

@ -8,8 +8,9 @@ stylesheets[all][] = css/islandora.base.css
stylesheets[all][] = css/islandora.theme.css
files[] = includes/mime_detect.inc
files[] = includes/dublin_core.inc
files[] = includes/IslandoraTuque.inc
files[] = includes/IslandoraTuqueWrapper.inc
files[] = includes/islandora_tuque.inc
files[] = includes/islandora_tuque_wrapper.inc
files[] = tests/islandora_web_test_case.inc
files[] = tests/islandora_authtokens.test
files[] = tests/islandora_hooks.test
php = 5.3

197
islandora.module

@ -37,14 +37,14 @@ define('FEDORA_MANAGE_PROPERTIES', 'manage object properties');
// Hooks
define('ISLANDORA_VIEW_HOOK', 'islandora_view_object');
define('ISLANDORA_EDIT_HOOK', 'islandora_edit_object');
define('ISLANDORA_PRE_INGEST_HOOK', 'islandora_ingest_pre_ingest');
define('ISLANDORA_POST_INGEST_HOOK', 'islandora_ingest_post_ingest');
define('ISLANDORA_PRE_PURGE_OBJECT_HOOK', 'islandora_pre_purge_object');
define('ISLANDORA_POST_PURGE_OBJECT_HOOK', 'islandora_post_purge_object');
// @todo Add Documentation.
define('ISLANDORA_OBJECT_INGESTED_HOOK', 'islandora_object_ingested');
define('ISLANDORA_OBJECT_MODIFIED_HOOK', 'islandora_object_modified');
define('ISLANDORA_OBJECT_PURGED_HOOK', 'islandora_object_purged');
define('ISLANDORA_DATASTREAM_INGESTED_HOOK', 'islandora_datastream_ingested');
define('ISLANDORA_DATASTREAM_MODIFIED_HOOK', 'islandora_datastream_modified');
define('ISLANDORA_DATASTREAM_PURGED_HOOK', 'islandora_datastream_purged');
define('ISLANDORA_INGEST_STEP_HOOK', 'islandora_ingest_steps');
define('ISLANDORA_PRE_PURGE_DATASTREAM_HOOK', 'islandora_pre_purge_datastream');
define('ISLANDORA_POST_PURGE_DATASTREAM_HOOK', 'islandora_post_purge_datastream');
define('ISLANDORA_EDIT_DATASTREAM_HOOK', 'islandora_edit_datastream');
/**
* Implements hook_menu().
@ -541,7 +541,6 @@ function islandora_default_islandora_view_object($object) {
* A IslandoraTuque instance
*/
function islandora_get_tuque_connection($user = NULL, $url = NULL) {
module_load_include('inc', 'islandora', 'includes/IslandoraTuque');
$tuque = &drupal_static(__FUNCTION__);
if (!$tuque) {
if (IslandoraTuque::exists()) {
@ -578,9 +577,7 @@ function islandora_object_load($object_id) {
$tuque = islandora_get_tuque_connection();
if ($tuque) {
try {
$object = $tuque->repository->getObject(urldecode($object_id));
drupal_alter('islandora_object', $object);
return $object;
return $tuque->repository->getObject(urldecode($object_id));
} catch (Exception $e) {
if ($e->getCode() == '404') {
return FALSE;
@ -744,124 +741,33 @@ function islandora_islandora_undeletable_datastreams(array $models) {
}
/**
* Ingest the given object into Fedora calling its pre/post hooks as well.
*
* @todo will be cleaned up in the future
* Ingest the given object.
*
* @param NewFedoraObject $object
* An ingestable FedoraObject.
*
* @return FedoraObject
* The ingested FedoraObject, after running the pre/post ingest hooks.
* Returns FALSE if the ingest failed.
* The ingested FedoraObject.
*/
function islandora_add_object(NewFedoraObject &$object) {
islandora_pre_add_object($object);
try {
$object->repository->ingestObject($object);
islandora_post_add_object($object);
return $object;
} catch (Exception $e) {
watchdog('islandora', 'Failed to ingest object: @pid</br>code: @code<br/>message: @msg', array(
'@pid' => $object->id,
'@code' => $e->getCode(),
'@msg' => $e->getMessage()), WATCHDOG_ERROR);
}
return FALSE;
}
/**
* Calls the ISLANDORA_PRE_INGEST_HOOK hooks.
*
* @param NewFedoraObject $object
* An ingestable FedoraObject.
*/
function islandora_pre_add_object(NewFedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_PRE_INGEST_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object);
}
}
/**
* Calls the ISLANDORA_POST_INGEST_HOOK hooks.
*
* @param FedoraObject $object
* A recently ingestable FedoraObject.
*/
function islandora_post_add_object(FedoraObject $object) {
foreach (islandora_build_hook_list(ISLANDORA_POST_INGEST_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object);
}
return $object->repository->ingestObject($object);
}
/**
* Deletes the given object into Fedora calling its pre/post hooks as well.
* Delete's or purges the given object.
*
* @param FedoraObject $object
* An object to delete.
*
* @return FedoraObject
* @return bool
* The ingested FedoraObject, after running the pre/post ingest hooks.
*/
function islandora_delete_object(FedoraObject &$object) {
$object_id = $object->id;
$models = $object->models;
$action = islandora_pre_delete_object($object);
switch ($action) {
case 'blocked':
// Do nothing.
return FALSE;
case 'delete':
// Change the state to deleted.
$object->delete();
islandora_post_delete_object($object_id, $models);
return TRUE;
default:
// Purge
$object->repository->purgeObject($object_id);
islandora_post_delete_object($object_id, $models);
$object = NULL;
return TRUE;
}
}
/**
* Calls the ISLANDORA_PRE_PURGE_OBJECT_HOOK hooks.
*
* @param FedoraObject $object
* The object that is about to be deleted.
*/
function islandora_pre_delete_object(FedoraObject $object) {
module_load_include('inc', 'islandora', 'includes/utilities');
$results = array();
foreach (islandora_build_hook_list(ISLANDORA_PRE_PURGE_OBJECT_HOOK, $object->models) as $hook) {
$results = array_merge_recursive($results, module_invoke_all($hook, $object));
}
$action = (isset($results['block']) && $results['block']) ? 'block' : FALSE;
$action = (!$action && isset($results['delete']) && $results['delete']) ? 'delete' : $action;
$action = !$action ? 'purge' : $action;
return $action;
return $object->repository->purgeObject($object->id);
}
/**
* Calls the ISLANDORA_POST_PURGE_OBJECT_HOOK hooks.
*
* @param string $object_id
* The object id of an the recently deleted object.
* @param array $models
* The list of content models the delete object subsribed to.
*/
function islandora_post_delete_object($object_id, array $models) {
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_POST_PURGE_OBJECT_HOOK, $models) as $hook) {
module_invoke_all($hook, $object_id, $models);
}
}
/**
* Delete's/Purges the given datastream.
* Delete's or purges the given datastream.
*
* @throws Exception
* Which types are undefined, but more than likely because of the hooks
@ -870,79 +776,12 @@ function islandora_post_delete_object($object_id, array $models) {
* @param FedoraDatastream $datastream
* The datastream to delete.
*
* @return boolean
* TRUE is returned if the datastream was Deleted/Purged, FALSE if it was
* blocked.
* @return bool
* TRUE if successful, FALSE otherwise.
*/
function islandora_delete_datastream(FedoraDatastream &$datastream) {
$datastream_id = $datastream->id;
$object = $datastream->parent;
$action = islandora_pre_delete_datastream($datastream);
switch ($action) {
case 'blocked':
// Do nothing.
return FALSE;
case 'delete':
// Change the state to deleted.
$object[$datastream_id]->state = 'D';
// @todo Differentiate between delete/purge in the hooks.
islandora_post_delete_datastream($object, $datastream_id);
return TRUE;
default:
// Purge
$object->purgeDatastream($datastream_id);
islandora_post_delete_datastream($object, $datastream_id);
$datastream = NULL;
return TRUE;
}
}
/**
* The default behaviour is to 'purge' the datastream but this can be overridden
* by modules that implement the 'islandora_pre_purge_datastream' hook.
*
* @todo make this an alter.
*
* The returned array can include a 'block' => TRUE
* pair which will prevent the datastream from being deleted if it particularly
* needed for a certain function. Returning 'delete' => TRUE will cause the
* datastream to be put into a deleted state.
*
* @param FedoraDatastream $datastream
* The datastream to delete.
*
* @return string
* The action to take when deleting the given datastream, either 'purge',
* 'delete', or 'block'.
*/
function islandora_pre_delete_datastream(FedoraDatastream $datastream) {
module_load_include('inc', 'islandora', 'includes/utilities');
$results = array();
foreach (islandora_build_hook_list(ISLANDORA_PRE_PURGE_DATASTREAM_HOOK, $datastream->parent->models) as $hook) {
// Not sure this will work the greatest, probably an alter would be better..
$results = array_merge_recursive($results, module_invoke_all($hook, $datastream));
}
$action = (isset($results['block']) && $results['block']) ? 'block' : FALSE;
$action = (!$action && isset($results['delete']) && $results['delete']) ? 'delete' : $action;
$action = !$action ? 'purge' : $action;
return $action;
}
/**
* Calls the post purge datastream hooks.
*
* @todo Should differentiate between purging/deleting.
*
* @param FedoraObject $object
* The parent object of the deleted datastream.
* @param string $datastream_id
* The datastream id of the deleted datastream.
*/
function islandora_post_delete_datastream(FedoraObject $object, $datastream_id) {
module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_POST_PURGE_DATASTREAM_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object, $datastream_id);
}
return $object->purgeDatastream($datastream->id);
}
/**

3
tests/README

@ -0,0 +1,3 @@
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.

6
tests/default.test_config.ini

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

48
tests/islandora_authtokens.test

@ -1,7 +1,15 @@
<?php
/**
* @file
* Test Authentication Tokens.
*/
class IslandoraAuthtokensTestCase extends IslandoraWebTestCase {
/**
* Get test information for display.
*/
public static function getInfo() {
return array(
'name' => 'Islandora Authorization Tokens',
@ -10,45 +18,50 @@ class IslandoraAuthtokensTestCase extends IslandoraWebTestCase {
);
}
/**
* Set up data for the tests.
*/
public function setUp() {
parent::setUp(array('islandora'));
parent::setUp();
}
/**
* Test redeeming invalid tokens.
*/
public function testRedeemInvalidToken() {
module_load_include('inc', 'islandora', 'includes/islandora_authtokens');
// get a token
$token = islandora_get_object_token('test:pid', 'woot', 1);
$this->assertTrue($token, 'Token was generated correctly.', 'Unit Tests');
// redeem a token that doesn't exist with real pid and dsid
// Redeem a token that doesn't exist with real pid and dsid.
$account = islandora_validate_object_token('test:pid', 'woot', 'foo');
$this->assertFalse($account, 'Redeeming an token that doesn\'t exist returns FALSE', 'Unit Tests');
}
/**
* Test redeeming valid tokens.
*/
public function testRedeemValidToken() {
module_load_include('inc', 'islandora', 'includes/islandora_authtokens');
// change the current user
// Change the current user.
global $user;
$user_backup = $user;
$test_account = $this->drupalCreateUser();
$user = $test_account;
$token = islandora_get_object_token('test:pid', 'woot', 1);
// logout again
// Logout again.
$user = $user_backup;
$token_account = islandora_validate_object_token('test:pid', 'woot', $token);
$this->assertEqual($token_account->uid, $test_account->uid, 'UID from token is correct', 'Unit Tests');
$this->assertEqual($token_account->pass, $test_account->pass, 'Pass from token is correct', 'Unit Tests');
$this->assertEqual($token_account->name, $test_account->name, 'Name from token is correct', 'Unit Tests');
}
/**
* Test tokened datastream view without XACML.
*/
public function testTokenedViewDatastreamWithoutXacml() {
// ingest the fixture
// Ingest the fixture.
$fixture_path = drupal_get_path('module', 'islandora') . '/tests/fixtures/bug.jp2';
$tuque = islandora_get_tuque_connection();
$newpid = "{$this->randomName()}:{$this->randomName()}";
@ -67,8 +80,8 @@ class IslandoraAuthtokensTestCase extends IslandoraWebTestCase {
$this->drupalGet("islandora/object/{$newpid}/datastream/JP2/view");
$this->assertResponse(200, 'Page loaded as the authorized user');
// do some voodoo to get a token as the user we are connecting as
// to do this we need to change the user we are logged in as
// Do some voodoo to get a token as the user we are connecting as
// to do this we need to change the user we are logged in as.
module_load_include('inc', 'islandora', 'includes/islandora_authtokens');
global $user;
$backup = $user;
@ -84,11 +97,14 @@ class IslandoraAuthtokensTestCase extends IslandoraWebTestCase {
$this->drupalGet("islandora/object/{$newpid}/datastream/JP2/view", array('query' => array('token' => $token)));
$this->assertResponse(403, 'Token is unable to be reused');
// delete fixture object
// Delete fixture object.
$tuque->repository->purgeObject($newpid);
}
/**
* This will test something someday.
*/
public function testTokenedViewDatastreamWithXacml() {
// we need to add this test.
// We need to add this test.
}
}

213
tests/islandora_hooks.test

@ -0,0 +1,213 @@
<?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 IslandoraHooksTestCase extends IslandoraWebTestCase {
/**
* Gets info to display to describe this test.
*
* @see IslandoraWebTestCase::getInfo()
*/
public static function getInfo() {
return array(
'name' => 'Islandora Hooks',
'description' => 'Ensure that the hooks for ingestion/purge/modification are called at the appropriate times.',
'group' => 'Islandora',
);
}
/**
* Creates an admin user and a connection to a fedora repository.
*
* @see IslandoraWebTestCase::setUp()
*/
public function setUp() {
parent::setUp('islandora_hooks_test', 'devel');
$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:testIngestedObjectHook',
'test:testBlockedIngestedObjectHook',
'test:testModifiedObjectHook',
'test:testPurgedObjectHook',
'test:testIngestedDatastreamHook',
'test:testModifiedDatastreamHook',
'test:testPurgedDatastreamHook',
);
foreach ($objects as $object) {
try {
$object = $this->repository->getObject($object);
$object->label = "Don't Block";
$this->repository->purgeObject($object->id);
}
catch(Exception $e) {
// Meh... Either it didn't exist or the purge failed.
}
}
}
/**
* Test ALL THE HOOKS!.
*/
public function testHooks() {
// Test ingesting with FedoraRepository::ingestObject().
$object = $this->repository->constructObject('test:testIngestedObjectHook');
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK] = FALSE;
$this->repository->ingestObject($object);
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called "hook_islandora_object_alter" when ingesting via FedoraRepository::ingestObject.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called ISLANDORA_OBJECT_INGESTED_HOOK when ingesting via FedoraRepository::ingestObject.');
$this->repository->purgeObject($object->id);
// Test blocking the ingest.
$object = $this->repository->constructObject('test:testIngestedObjectHook');
$object->label = 'block';
try {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK] = FALSE;
$this->repository->ingestObject($object);
$this->fail('Blocked ingest should throw an Exception.');
$this->repository->purgeObject($object->id);
}
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.');
}
// Test modifying via set magic functions.
$object = $this->repository->constructObject('test:testModifiedObjectHook');
$this->repository->ingestObject($object);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
$object->label = "New Label!";
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called "hook_islandora_object_alter" when modifying via set magic functions.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called ISLANDORA_OBJECT_MODIFIED_HOOK when modifying via set magic functions.');
// Test blocking the modification.
try {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
$object->label = 'block';
$this->fail('Blocked modify should throw an Exception.');
}
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.');
$this->assertFALSE($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called ISLANDORA_OBJECT_MODIFIED_HOOK when blocking modifying via set magic functions.');
}
$this->repository->purgeObject($object->id);
// Test purging with FedoraRepository::purgeObject().
$object = $this->repository->constructObject('test:testPurgedObjectHook');
$this->repository->ingestObject($object);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$this->repository->purgeObject($object->id);
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when purging via FedoraRepository::purgeObject.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when purging via FedoraRepository::purgeObject.');
// Test deleting.
$object = $this->repository->constructObject('test:testPurgedObjectHook');
$this->repository->ingestObject($object);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$object->delete();
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when deleting via FedoraObject::delete.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when purging via FedoraObject::delete.');
$this->repository->purgeObject($object->id);
// Test alter blocking.
$object = $this->repository->constructObject('test:testPurgedObjectHook');
$this->repository->ingestObject($object);
try {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$object->label = 'block';
$this->repository->purgeObject($object->id);
$this->fail('Blocked modify should throw an Exception.');
}
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.');
}
// Test alter delete.
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = FALSE;
$object->label = 'delete';
$this->repository->purgeObject($object->id);
$this->assertEqual($object->state, 'D', '"hook_islandora_object_alter" prevented purge and deleted the object.');
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when preventing purge and deleting.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when preventing purge and deleting.');
$object->label = 'Something other than delete';
$this->repository->purgeObject($object->id);
// Test ingesting with FedoraRepository::ingestObject().
$object = $this->repository->constructObject('test:testIngestedDatastreamHook');
$this->repository->ingestObject($object);
$ds = $object->constructDatastream('TEST');
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = FALSE;
$object->ingestDatastream($ds);
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK], 'Called "hook_islandora_datastream_alter" when ingesting via FedoraObject::ingestDatastream.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK], 'Called ISLANDORA_DATASTREAM_INGESTED_HOOK when ingesting via FedoraObject::ingestDatastream.');
$this->repository->purgeObject($object->id);
// Test modifying a datastream.
$object = $this->repository->constructObject('test:testModifiedDatastreamHook');
$this->repository->ingestObject($object);
$ds = $object->constructDatastream('TEST');
$object->ingestDatastream($ds);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
$ds->label = "New Label!";
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called "hook_islandora_datastream_alter" when modifying via set magic functions.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when modifying via set magic functions.');
// Test blocking modifying.
try {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
$ds->label = 'block';
$this->fail('Blocked modify should throw an Exception.');
}
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.');
}
$this->repository->purgeObject($object->id);
// Test purging with FedoraRepository::purgeObject().
$object = $this->repository->constructObject('test:testPurgedDatastreamHook');
$this->repository->ingestObject($object);
$ds = $object->constructDatastream('TEST');
$object->ingestDatastream($ds);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_PURGED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_PURGED_HOOK] = FALSE;
$object->purgeDatastream($ds->id);
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_PURGED_HOOK], 'Called "hook_islandora_datastream_alter" when purging via FedoraObject::purgeDatastream.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_PURGED_HOOK], 'Called ISLANDORA_DATASTREAM_PURGED_HOOK when purging via FedoraObject::purgeDatastream.');
$this->repository->purgeObject($object->id);
}
}

7
tests/islandora_hooks_test.info

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

152
tests/islandora_hooks_test.module

@ -0,0 +1,152 @@
<?php
/**
* @file
* Implements hooks that get tested by islandora_hooks.test
*/
/**
* Implements hook_islandora_object_alter().
*/
function islandora_hooks_test_islandora_object_alter(AbstractFedoraObject $object, array &$context) {
switch ($context['action']) {
case 'ingest':
if ($object->id == 'test:testIngestedObjectHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK] = TRUE;
if ($object->label == 'block') {
$context['block'] = TRUE;
}
}
break;
case 'modify':
if ($object->id == 'test:testModifiedObjectHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE;
if (isset($context['params']['label']) && $context['params']['label'] == 'block') {
$context['block'] = TRUE;
}
}
elseif ($object->id == 'test:testPurgedObjectHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = TRUE;
if (isset($context['params']['label']) && $context['params']['label'] == 'block') {
$context['block'] = TRUE;
}
elseif (isset($context['params']['label']) && $context['params']['label'] == 'delete') {
$context['delete'] = TRUE;
}
}
break;
case 'purge':
if ($object->id == 'test:testPurgedObjectHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = TRUE;
if ($object->label == 'block') {
$context['block'] = TRUE;
}
elseif ($object->label == 'delete') {
$context['delete'] = TRUE;
}
}
break;
}
}
/**
* Implements hook_islandora_object_alter().
*/
function islandora_hooks_test_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) {
switch ($context['action']) {
case 'ingest':
if ($object->id == 'test:testIngestedDatastreamHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = TRUE;
if ($datastream->label == 'block') {
$context['block'] = TRUE;
}
}
break;
case 'modify':
if ($object->id == 'test:testModifiedDatastreamHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE;
if (isset($context['params']['dsLabel']) && $context['params']['dsLabel'] == 'block') {
$context['block'] = TRUE;
}
}
elseif ($object->id == 'test:testPurgedDatastreamHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE;
if (isset($context['params']['dsLabel']) && $context['params']['dsLabel'] == 'block') {
$context['block'] = TRUE;
}
elseif (isset($context['params']['dsLabel']) && $context['params']['dsLabel'] == 'delete') {
$context['delete'] = TRUE;
}
}
break;
case 'purge':
if ($object->id == 'test:testPurgedDatastreamHook') {
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE;
if ($datastream->label == 'block') {
$context['block'] = TRUE;
}
elseif ($datastream->label == 'delete') {
$context['delete'] = TRUE;
}
}
break;
}
}
/**
* Implements hook_islandora_object_ingested().
*/
function islandora_hooks_test_islandora_object_ingested(FedoraObject $object) {
if ($object->id == 'test:testIngestedObjectHook') {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK] = TRUE;
}
}
/**
* Implements hook_islandora_object_modified().
*/
function islandora_hooks_test_islandora_object_modified(FedoraObject $object) {
if ($object->id == 'test:testModifiedObjectHook') {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE;
}
}
/**
* Implements hook_islandora_object_purged().
*/
function islandora_hooks_test_islandora_object_purged($pid) {
if ($pid == 'test:testPurgedObjectHook') {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = TRUE;
}
}
/**
* Implements hook_islandora_datastream_ingested().
*/
function islandora_hooks_test_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) {
if ($object->id == 'test:testIngestedDatastreamHook' && $datastream->id == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = TRUE;
}
}
/**
* Implements hook_islandora_datastream_modified().
*/
function islandora_hooks_test_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) {
if ($object->id == 'test:testModifiedDatastreamHook' && $datastream->id == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE;
}
}
/**
* Implements hook_islandora_datastream_purged().
*/
function islandora_hooks_test_islandora_datastream_purged(FedoraObject $object, $dsid) {
if ($object->id == 'test:testPurgedDatastreamHook' && $dsid == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE;
}
}

108
tests/islandora_web_test_case.inc

@ -1,36 +1,124 @@
<?php
/**
* @file
* Defines the class IslandoraWebTestCase, which allows tests to access Fedora.
*/
class IslandoraWebTestCase extends DrupalWebTestCase {
/**
* Sets up the Drupal filter to access this test Drupal instances database.
*
* @see DrupalWebTestCase::setUp()
*/
public function setUp() {
$args = func_get_args();
call_user_func_array(array('parent', 'setUp'), $args);
$args = (isset($args[0]) && is_array($args[0])) ? $args[0] : $args;
// Always enable islandora.
$args[] = 'islandora';
parent::setUp($args);
$this->configuration = $this->getTestConfiguration();
if ($this->configuration['use_drupal_filter']) {
$this->backUpDrupalFilter();
$this->setUpDrupalFilter();
}
$this->createAdminUser();
}
$islandora_path = drupal_get_path('module', 'islandora');
$this->config_info = parse_ini_file("$islandora_path/tests/test_config.ini");
$connection_info = Database::getConnectionInfo('default');
/**
* Parses and returns the settings from the test configuration file.
*
* If no install specific test_config.ini file is found, it will use the
* assumed default configs found in default.test_config.ini.
*
* @return array
* The test configuration.
*
* @see parse_ini_file()
*/
protected function getTestConfiguration() {
$path = drupal_get_path('module', 'islandora');
if (file_exists("$path/tests/test_config.ini")) {
$this->pass('Using custom test configuration.');
return parse_ini_file("$path/tests/test_config.ini");
}
elseif (file_exists("$path/tests/default.test_config.ini")) {
$this->pass('Using default test configuration.');
return parse_ini_file("$path/tests/default.test_config.ini");
}
throw new Exception('Required default.test_config.ini/test_config.ini file not found');
}
$this->original_drupal_fiter = file_get_contents($this->config_info['filter_drupal_file']);
/**
* Stores the content of the Drupal Filter for later restoration.
*/
protected function backUpDrupalFilter() {
if (file_exists($this->configuration['filter_drupal_file'])) {
$this->originalDrupalFilterContent = file_get_contents($this->configuration['filter_drupal_file']);
}
else {
throw new Exception('Failed to find the required Drupal Filter configuration file.');
}
}
/**
* Sets up a drupal filter that can read for the tests users table.
*/
protected function setUpDrupalFilter() {
$connection_info = Database::getConnectionInfo('default');
$drupal_filter_dom = new DomDocument();
$drupal_filter_dom->loadXML($this->original_drupal_fiter);
$drupal_filter_dom->loadXML($this->originalDrupalFilterContent);
$drupal_filter_xpath = new DOMXPath($drupal_filter_dom);
$server = $connection_info['default']['host'];
$dbname = $connection_info['default']['database'];
$user = $connection_info['default']['username'];
$password = $connection_info['default']['password'];
$port = $connection_info['default']['port'] ? $connection_info['default']['port'] : '3306';
$prefix = $connection_info['default']['prefix']['default'];
$results = $drupal_filter_xpath->query("/FilterDrupal_Connection/connection[@server='$server' and @dbname='$dbname' and @user='$user' and @password='$password' and @port='$port']/sql");
$results->item(0)->nodeValue = "SELECT DISTINCT u.uid AS userid, u.name AS Name, u.pass AS Pass, r.name AS Role FROM ({$prefix}users u LEFT JOIN {$prefix}users_roles ON u.uid={$prefix}users_roles.uid) LEFT JOIN {$prefix}role r ON r.rid={$prefix}users_roles.rid WHERE u.name=? AND u.pass=?;";
file_put_contents($this->configuration['drupal_filter_file'], $drupal_filter_dom->saveXML());
}
file_put_contents($this->config_info['filter_drupal_file'], $drupal_filter_dom->saveXML());
/**
* 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'];
$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;
}
/**
* Stores the content of the Drupal Filter for later restoration.
*/
protected function restoreDrupalFilter() {
$file = $this->configuration['filter_drupal_file'];
if (isset($this->originalDrupalFilterContent)) {
file_put_contents($file, $this->originalDrupalFilterContent);
}
elseif (file_exists($file)) {
// Remove if there was never an original.
drupal_unlink($file);
}
}
/**
* Restores the original Drupal filter, frees any allocated resources.
*
* @see DrupalWebTestCase::tearDown()
*/
public function tearDown() {
file_put_contents($this->config_info['filter_drupal_file'], $this->original_drupal_fiter);
if ($this->configuration['use_drupal_filter']) {
$this->restoreDrupalFilter();
}
unset($this->admin);
unset($this->configuration);
parent::tearDown();
}
}

4
tests/test_config.ini

@ -1,4 +0,0 @@
[fedora]
filter_drupal_file = "/usr/local/fedora/server/config/filter-drupal.xml"
admin_user = "fedoraAdmin"
admin_pass = "fedoraAdmin"
Loading…
Cancel
Save