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