Browse Source

Merge pull request #193 from adam-vessey/7.x-alter-hook-defs

Alter hook calls and update documentation to reflect it.
pull/196/head
Jonathan Green 12 years ago
parent
commit
7984b26ff8
  1. 114
      includes/islandora.ingest.inc
  2. 48
      includes/utilities.inc
  3. 196
      islandora.api.php
  4. 133
      islandora.module

114
includes/islandora.ingest.inc

@ -2,7 +2,7 @@
/** /**
* @file * @file
* This file contains ingest callback functions * This file contains ingest callback functions.
*/ */
/** /**
@ -16,23 +16,69 @@ function islandora_ingest_get_information(AbstractFedoraObject $collection_objec
} }
/** /**
* @TODO: needs documentation * Get an ingestable object.
*
* @deprecated
* Deprecated in favour of the more flexible
* islandora_ingest_new_object_prepare()--which this function has been made
* to call behind the scenes anyway.
*
* @param array $content_models
* An array of content models to which the new object should subscribe, where
* each content model is described by an associative array containing:
* - pid: The Fedora PID of the content model.
* @param string $collection_pid
* The collection to which the new object should belong.
* @param string $relationship
* The relationship this object will have to the collection.
* @param string $namespace
* The namespace in which the PID for the new object will be created.
*
* @return NewFedoraObject
* A NewFedoraObject which may be adjusted before ingesting.
*/ */
function islandora_ingest_get_object($content_models, $collection_pid, $relationship, $namespace) { function islandora_ingest_get_object($content_models, $collection_pid, $relationship, $namespace) {
module_load_include('inc', 'islandora', 'includes/tuque'); $models = array();
global $user; foreach ($content_models as $relation) {
$connection = new IslandoraTuque($user); $models[] = $relation['pid'];
$object = $connection->repository->constructObject($namespace);
foreach ($content_models as $content_model) {
$object->relationships->add(FEDORA_MODEL_URI, 'hasModel', $content_model['pid']);
} }
$object->relationships->add(FEDORA_RELS_EXT_URI, $relationship, $collection_pid);
module_invoke_all('islandora_ingest_pre_ingest', $object, $content_models, $collection_pid); return islandora_ingest_new_object_prepare($namespace, NULL, array(), $models, array(
return $object; array(
'pid' => $collection_pid,
'relationship' => $relationship,
),
), $collection_pid);
} }
/** /**
* @TODO: needs documentation * Prepare an ingestable object.
*
* @param string $namespace
* The namespace in which the PID for the new object will be created.
* @param string $label
* An optional label to apply to the object.
* @param array $datastreams
* A array of datastreams to add, where each datastream definition is an
* associative array containing:
* - dsid: The datastream ID.
* - label: An optional label for the datastream.
* - mimetype: A MIMEtype for the datastream; defaults to text/xml.
* - control_group: One of X, M, R and E; defaults to M.
* - datastream_file: A web-accessible path, for which we try to get an
* absolute path using url().
* @param array $content_models
* An array of content model PIDs to which the new object should subscribe.
* @param array $relationships
* An array of relationships, where each relationship is an associative array
* containing:
* - relationship: The predicate for the relationship, from the Fedora
* RELS-EXT namespace.
* - pid: The object for the relationship, to which we are creating the
* relationhsip.
*
* @return NewFedoraObject
* An ingestable NewFedoraObject.
*/ */
function islandora_ingest_new_object_prepare($namespace = NULL, $label = NULL, $datastreams = array(), $content_models = array(), $relationships = array(), $collection_pid = NULL) { function islandora_ingest_new_object_prepare($namespace = NULL, $label = NULL, $datastreams = array(), $content_models = array(), $relationships = array(), $collection_pid = NULL) {
// include Tuque library // include Tuque library
@ -86,20 +132,56 @@ function islandora_ingest_new_object_prepare($namespace = NULL, $label = NULL, $
$object->ingestDatastream($datastream); $object->ingestDatastream($datastream);
} }
module_invoke_all('islandora_ingest_pre_ingest', $object, $content_models, $collection_pid); module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list('islandora_ingest_pre_ingest', $content_models) as $hook) {
module_invoke_all($hook, $object, $content_models, $collection_pid);
}
return $object; return $object;
} }
/** /**
* @TODO: needs documentation * Ingest the given object into Fedora.
*
* @param NewFedoraObject $object
* An ingestable FedoraObject.
*
* @return FedoraObject
* The ingested FedoraObject, after running the post ingest hooks.
*/ */
function islandora_ingest_add_object(&$object) { function islandora_ingest_add_object(&$object) {
$object->repository->ingestObject($object); $object->repository->ingestObject($object);
module_invoke_all('islandora_ingest_post_ingest', $object);
return $object; module_load_include('inc', 'islandora', 'includes/utilities');
foreach (islandora_build_hook_list(ISLANDORA_POST_INGEST_HOOK, $object->models) as $hook) {
module_invoke_all($hook, $object);
} }
return $object;
}
/**
* Ingest an object.
*
* @param array $object_model
* An associative array containing the necessary parameters to create the
* desired object:
* - pid: The PID with which the object will be created.
* - label: An optional label to apply to the object.
* - datastreams: Same as the "datastreams" array accepted by
* islandora_ingest_new_object_prepare().
* - cmodel: Either an array of content models as accepted by
* islandora_ingest_new_object_prepare(), or a single content model PID to add
* to the object.
* - parent: Either an array of parents, or a single parent PID to which to
* relate to; uses isMemberOfCollection by default.
* - relationships: An array of relationships as accepted by
* islandora_ingest_new_object_prepare().
*
* @return FedoraObject
* An FedoraObject which has been ingested into Fedora.
*/
function islandora_ingest_new_object($object_model) { function islandora_ingest_new_object($object_model) {
// prepare variables // prepare variables
// namespace // namespace

48
includes/utilities.inc

@ -8,6 +8,8 @@
/** /**
* Convert bytes to human readable format * Convert bytes to human readable format
* *
* XXX: Shouldn't Drupal's format_size() be preferred?
*
* @param integer bytes Size in bytes to convert * @param integer bytes Size in bytes to convert
* @return string * @return string
*/ */
@ -104,3 +106,49 @@ function islandora_describe_repository($url) {
return FALSE; return FALSE;
} }
} }
/**
* Build a list of all the hooks to call.
*
* Concatenates the each pid (escaped) to the hook name, for calling in
* module_invoke_all().
*
* @param string $hook
* A hook to call.
* @param array $pids
* An array of PIDs (probably content models).
*
* @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.
*/
function islandora_build_hook_list($hook, $pids = array()) {
$hooks = array();
foreach ($pids as $model) {
$hooks[] = islandora_escape_pid_for_function($model) . '_' . $hook;
}
$hooks[] = $hook;
return $hooks;
}
/**
* Escape a Fedora PID to be valid inside of a PHP function name.
*
* Originally intended to allow inclusion of a PID in a module_invoke_all()
* call.
*/
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
);
}

196
islandora.api.php

@ -6,120 +6,192 @@
*/ */
/** /**
* remove a datastream from a repository object * Generate a repository objects view.
* @param object $fedora_object *
* tuque FedoraObject * @param FedoraObject $fedora_object
* @param string $datastream_id * A Tuque FedoraObject being operated on.
* @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.
*
* @return array
* An array whose values are markup.
*/ */
function hook_islandora_purge_datastream($fedora_object, $datastream_id) {} function hook_islandora_view_object($fedora_object, $user, $page_number, $page_size) {}
/** /**
* Generate an object's display for the given content model.
* *
* @param type $object * Content models PIDs have colons and hyphens changed to underscores, to
* tuque FedoraObject * create the hook name.
*
* @param type $fedora_object
* A Tuque FedoraObject
*
* @return array
* An array whose values are markup.
*/ */
function hook_islandora_purge_object($islandora_object) {} function hook_CMODEL_PID_islandora_view_object($fedora_object) {}
/** /**
* allows modules to add to a repository objects display. If you implement this * Alter display output after it has been generated.
* hook you should also register your module for view with the get types hook.
*
* islandora gets all displays back in an array and iterates over them. the order
* they are displayed is based on the order of the key of the array that each
* module returns.
*
* your module may also want to register a varible that says whether or not it
* should be part of the default display. Modules can also add secondary tabs as
* a way to add there output to an islandora display. the basic image module has
* samples of both (the secondary tabs examples are commented out)
* *
* @param type $islandora_object * @param FedoraObject $fedora_object
* tuque FedoraObject * A Tuque FedoraObject being operated on.
* @param array $arr
* An arr of rendered views.
*/ */
function hook_islandora_view_object($islandora_object) {} function hook_islandora_view_object_alter(&$fedora_object, &$arr) {}
/** /**
* returns an array listing object types provided by sub modules * Generate an object's management display.
* Ex. array($types['islandora:collectionCModel'][ISLANDORA_VIEW_HOOK] = variable_get('islandora_basic_collection_use_for_default_tab', TRUE); *
* $types['islandora:collectionCModel'][ISLANDORA_EDIT_HOOK] = FALSE; * @param type $fedora_object
* A Tuque FedoraObject
* *
* @return array * @return array
* An array whose values are markup.
*/ */
function hook_islandora_get_types() {} function hook_islandora_edit_object($fedora_object) {}
/** /**
* allows modules to define an object edit page by cmodel * Generate an object's management display for the given content model.
* *
* your module should return true for ISLANDORA_EDIT_HOOK in its get_types function * Content models PIDs have colons and hyphens changed to underscores, to
* create the hook name.
* *
* islandora provides a default implementation that should work for most use cases * @param type $fedora_object
* @param string $islandora_object * A Tuque FedoraObject
* @return string
* *
* @return array
* An array whose values are markup.
*/ */
function hook_islandora_edit_object($islandora_object) {} function hook_CMODEL_PID_islandora_edit_object($fedora_object) {}
/** /**
* allows modules to alter the fedora object before it is pass through the edit * Allow management display output to be altered.
* hooks *
* @param type $islandora_object * @param type $fedora_object
* a tugue FedoraObject * A Tuque FedoraObject
* @param type $arr
* an arr of rendered views
*/ */
function hook_islandora_edit_object_alter($islandora_object) {} function hook_islandora_edit_object_alter(&$fedora_object, &$arr) {}
/**
* Allows modules to add to an objects ingest process.
*
* @param FedoraObject $fedora_object
* A Tuque FedoraObject.
*/
function hook_islandora_ingest_post_ingest($fedora_object) {}
/** /**
* creates and populates a php Fedora object. * Allow modules to add to the ingest process of a specific content model.
*/ */
function hook_islandora_preingest_alter() {} function hook_CMODEL_PID_islandora_ingest_post_ingest($fedora_object) {}
/** /**
* modules can implement this hook to add or remove datastreams after an * Allows modules to add to a repository objects view/edit(/misc) process.
* object has been ingested.
* *
* Each module should check for the newly ingested repository objects content * If you implement this hook you must also register your module with
* model to make sure it is a type of object they want to act on. * hook_islandora_hook_info().
* *
* @param type $islandora_object * @param FedoraObject $fedora_object
* tugue FeodoraObject * A Tuque FedoraObject.
*
* @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.
*/
function hook_islandora_pre_purge_object($fedora_object) {}
/**
* Allow modules to react to the purge process of a specific content model.
*
* @see hook_islandora_pre_purge_object()
*/ */
function hook_islandora_postingest($islandora_object) {} function hook_CMODEL_PID_islandora_pre_purge_object($fedora_object) {}
/** /**
* Register potential ingest routes. Implementations should return an array containing possible routes. * Register potential ingest routes.
* Ex. array( *
* array('name' => t('Ingest Route Name'), 'url' => 'ingest_route/url', 'weight' => 0), * Implementations should return an array containing possible routes.
* );
*/ */
function hook_islandora_ingest_registry($collection_object) {} function hook_islandora_ingest_registry($collection_object) {
$reg = array(
array(
'name' => t('Ingest Route Name'),
'url' => 'ingest_route/url',
'weight' => 0,
),
);
return $reg
}
/** /**
* Register a datastream edit route/form. * Register a datastream edit route/form.
*
* @param $islandora_object * @param $islandora_object
* @param $ds_id * @param $ds_id
*/ */
function hook_islandora_edit_datastream_registry($islandora_object, $ds_id) {} function hook_islandora_edit_datastream_registry($islandora_object, $ds_id) {}
/** /**
* alter an object before it gets used further down the stack * Alter an object before it gets used further down the stack.
*
* @param type $object * @param type $object
* a tuque FedoraObject * A Tuque FedoraObject
*/ */
function hook_islandora_object_alter($fedora_object) {} function hook_islandora_object_alter($fedora_object) {}
/** /**
* insert or remove rendered elements by implementing this function * Allow modification of an object before ingesting.
* in your module
* @param type $arr
* an arr of rendered views
*/
function hook_islandora_display_alter($arr) {}
/**
* *
* @param type $islandora_object * @param type $islandora_object
* a tuque FedoraObject * A Tuque FedoraObject
* @param array $content_models * @param array $content_models
* @param string $collection_pid * @param string $collection_pid
*/ */
function hook_islandora_ingest_pre_ingest($islandora_object, $content_models, $collection_pid) {} function hook_islandora_ingest_pre_ingest($islandora_object, $content_models, $collection_pid) {}
/**
* Allow modification of objects of a certain content model before ingesting.
*
* @see hook_islandora_ingest_pre_ingest()
*/
function hook_CMODEL_PID_islandora_ingest_pre_ingest($islandora_object, $content_models, $collection_pid) {}
/**
* Allow modules to setup for the purge of a datastream.
*
* @param object $datastream
* A Tuque FedoraDatastream object.
*/
function hook_islandora_pre_purge_datastream($datastream) {}
/**
* Allow modules to react after a datastream is purged.
*
* @param object $object
* A Tuque FedoraObject.
* @param string $dsid
* A id of the former datastream.
*/
function hook_islandora_post_purge_datastream($object, $dsid) {}
/**
* Allow modules to react post-purge.
*
* @param string $object_id
* The former object's PID.
* @param array $content_models
* An array containing the models to which the former object.
*/
function hook_islandora_post_purge_object($object_id, $content_models) {}

133
islandora.module

@ -31,9 +31,11 @@ define('FEDORA_PURGE', 'delete fedora objects and datastreams');
define('FEDORA_MODIFY_STATE', 'modify fedora state'); define('FEDORA_MODIFY_STATE', 'modify fedora state');
define('FEDORA_MANAGE', 'manage fedora items'); define('FEDORA_MANAGE', 'manage fedora items');
// hooks // Hooks
define('ISLANDORA_VIEW_HOOK', 'islandora_view_object'); define('ISLANDORA_VIEW_HOOK', 'islandora_view_object');
define('ISLANDORA_EDIT_HOOK', 'islandora_edit_object'); define('ISLANDORA_EDIT_HOOK', 'islandora_edit_object');
define('ISLANDORA_POST_INGEST_HOOK', 'islandora_ingest_post_ingest');
define('ISLANDORA_PRE_PURGE_OBJECT_HOOK', 'islandora_pre_purge_object');
/** /**
* Implements hook_menu(). * Implements hook_menu().
@ -249,14 +251,6 @@ function islandora_access_callback($object = NULL, $perm = NULL) {
return ($namespace_access && user_access($perm)); return ($namespace_access && user_access($perm));
} }
/**
* returns an array listing object types provided by sub modules
* @return array
*/
function islandora_get_types() {
return module_invoke_all('islandora_get_types');
}
function islandora_init() { function islandora_init() {
if (path_is_admin(current_path())) { if (path_is_admin(current_path())) {
drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css'); drupal_add_css(drupal_get_path('module', 'islandora') . '/css/islandora.admin.css');
@ -287,14 +281,30 @@ function islandora_edit_object($object) {
if (!$object) { if (!$object) {
return drupal_not_found(); return drupal_not_found();
} }
drupal_alter('islandora_edit_object', $object);
$arr = module_invoke_all('islandora_edit_object', $object); module_load_include('inc', 'islandora', 'includes/utilities');
$output = "";
foreach ($arr as $key => $value) { // Accumulate the output.
$output .= $value; //if we have multiple modules handle one cmodel we need to iterate over multiple $output = array();
// Call cmodel oriented variants first.
foreach (islandora_build_hook_list(ISLANDORA_EDIT_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
}
}
// Add in the default, if we did not get any results.
if (empty($output)) {
$output = islandora_default_islandora_edit_object($object);
} }
//we could do another module invoke all here to build the edit tab with a default implemented in this module?
return $output; arsort($output);
drupal_alter(ISLANDORA_EDIT_HOOK, $object, $output);
return implode('', $output);
} }
/** /**
@ -314,23 +324,25 @@ function islandora_edit_properties($object_id) {
} }
/** /**
* builds a default page for the edit tab * Builds a default page for the edit tab.
* *
* @param object $fedora_object * @param object $fedora_object
* A tuque Fedora Object * A tuque Fedora Object
*/ */
function islandora_islandora_edit_object($fedora_object) { function islandora_default_islandora_edit_object($fedora_object) {
$supported_models = islandora_get_types(); $output = theme('islandora_default_edit', array(
$output = ""; 'islandora_object' => $fedora_object,
foreach ($fedora_object->models as $model) { ));
if (isset($supported_models[$model][ISLANDORA_EDIT_HOOK]) && $supported_models[$model][ISLANDORA_EDIT_HOOK] == TRUE) {//another module is handling the view
return; return array('Default Edit output' => $output);
}
}
$output = theme('islandora_default_edit', array('islandora_object' => $fedora_object));
return array('Default edit output' => $output);
} }
/**
* Page callback for the path "islandora".
*
* Redirects to the view of the object indicated by the Drupal variable
* islandora_repository_pid.
*/
function islandora_view_default_object() { function islandora_view_default_object() {
$pid = variable_get('islandora_repository_pid', 'islandora:root'); $pid = variable_get('islandora_repository_pid', 'islandora:root');
drupal_goto("islandora/object/$pid"); drupal_goto("islandora/object/$pid");
@ -346,6 +358,8 @@ function islandora_view_default_object() {
*/ */
function islandora_view_object($fedora_object = NULL) { function islandora_view_object($fedora_object = NULL) {
module_load_include('inc', 'islandora', 'includes/breadcrumb'); module_load_include('inc', 'islandora', 'includes/breadcrumb');
module_load_include('inc', 'islandora', 'includes/utilities');
global $user; global $user;
if (!$fedora_object) { if (!$fedora_object) {
@ -358,37 +372,38 @@ function islandora_view_object($fedora_object = NULL) {
$page_number = (empty($_GET['page'])) ? '1' : $_GET['page']; $page_number = (empty($_GET['page'])) ? '1' : $_GET['page'];
$page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize']; $page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize'];
drupal_alter('islandora_object', $fedora_object); //modify object if required before it is passed along // Accumulate the output.
$arr = module_invoke_all('islandora_view_object', $fedora_object, $user, $page_number, $page_size); //allow submodules to decide how to handle content base on object type $output = array();
if (empty($arr)) {
//TODO: make sure we iterate over the array as they will be more then one cmodel per object // Call cmodel oriented variants first.
drupal_set_message(t('there was an error loading the view for Islandora object "%s"', array('%s' => $fedora_object->label)), 'error'); foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $fedora_object->models) as $hook) {
return ""; $temp = module_invoke_all($hook, $fedora_object, $user, $page_number, $page_size);
if (!empty($temp)) {
$output = array_merge_recursive($output, $temp);
} }
arsort($arr);
drupal_alter('islandora_display', $arr);
$output = "";
foreach ($arr as $key => $value) {
$output .= $value; //if we have multiple modules handle one cmodel we need to iterate over multiple
} }
return $output;
// Add in the default, if we did not get any results.
if (empty($output)) {
$output = islandora_default_islandora_view_object($fedora_object);
}
arsort($output);
drupal_alter(ISLANDORA_VIEW_HOOK, $fedora_object, $output);
return implode('', $output);
} }
/** /**
* The default view hook. If there are no modules registered to handle this objects cmodels or there are * If there are no modules registered to handle this objects cmodels or there are
* not any cmodels specified this will create a default display. * not any cmodels specified this will create a default display.
* *
* @param string $object_id * @param FedoraObject $object
* @return string * The object whose display we are to render.
* @return array
*/ */
function islandora_islandora_view_object($object) { function islandora_default_islandora_view_object($object) {
$supported_models = islandora_get_types();
$output = "";
foreach ($object->models as $model) {
if (isset($supported_models[$model][ISLANDORA_VIEW_HOOK]) && (boolean) $supported_models[$model][ISLANDORA_VIEW_HOOK] === TRUE) { //another module is handling the view
return;
}
}
$output = theme('islandora_default', array('islandora_object' => $object)); $output = theme('islandora_default', array('islandora_object' => $object));
return array('Default output' => $output); return array('Default output' => $output);
} }
@ -460,7 +475,7 @@ function islandora_permission() {
*/ */
function islandora_object_load($object_id) { function islandora_object_load($object_id) {
module_load_include('inc', 'islandora', 'includes/tuque'); module_load_include('inc', 'islandora', 'includes/tuque');
static $islandora_tuque = NULL; $islandora_tuque = &drupal_static(__FUNCTION__);
if (!$islandora_tuque) { if (!$islandora_tuque) {
$islandora_tuque = new IslandoraTuque(); $islandora_tuque = new IslandoraTuque();
@ -472,6 +487,8 @@ function islandora_object_load($object_id) {
} catch (Exception $e) { } catch (Exception $e) {
return NULL; return NULL;
} }
drupal_alter('islandora_object', $fedora_object);
return $fedora_object; return $fedora_object;
} }
else { else {
@ -500,8 +517,19 @@ function islandora_object_purge($object_id) {
drupal_set_message(t('Could not remove object, object not found')); drupal_set_message(t('Could not remove object, object not found'));
return; return;
} }
module_load_include('inc', 'islandora', 'includes/utilities');
$content_models = $object->models; $content_models = $object->models;
$arr = module_invoke_all('islandora_pre_purge_object', $object); // notify modules of pending deletion
$arr = array();
foreach (islandora_build_hook_list(ISLANDORA_PRE_PURGE_OBJECT_HOOK, $object->models) as $hook) {
$temp = module_invoke_all($hook, $object);
if (!empty($temp)) {
$arr = array_merge_recursive($arr, $temp);
}
}
if (isset($arr['delete']) && $arr['delete']) { if (isset($arr['delete']) && $arr['delete']) {
try { try {
$object->delete(); $object->delete();
@ -518,6 +546,7 @@ function islandora_object_purge($object_id) {
return ""; return "";
} }
} }
module_invoke_all('islandora_post_purge_object', $object_id, $content_models); // notify modules post deletion module_invoke_all('islandora_post_purge_object', $object_id, $content_models); // notify modules post deletion
} }

Loading…
Cancel
Save